在php文件上传前检查图片文件类型和大小

时间:2022-11-24 14:41:05

I have the following code:

我有以下代码:

$filecheck = basename($_FILES['imagefile']['name']);
  $ext = substr($filecheck, strrpos($filecheck, '.') + 1);
  if (($ext == "jpg" || $ext == "gif" || $ext == "png") && ($_FILES["imagefile"]["type"] == "image/jpeg" || $_FILES["imagefile"]["type"] == "image/gif" || $_FILES["imagefile"]["type"] == "image/png") && 
    ($_FILES["imagefile"]["size"] < 2120000)){
} else {
echo "F2";
die();
}

What i need to do is check if the uploaded file is a jpg/gif/png and that its less than 2 megs in size.

我需要做的是检查上传的文件是否为jpg/gif/png格式,并且其大小小于2兆。

If its larger than 2 megs, or not the right file type, i need to return/echo F2 (error code for api).

如果它大于2兆,或者不是正确的文件类型,我需要返回/echo F2 (api的错误代码)。

When i use the code above to process a 70k jpg file, it returns F2.

当我使用上面的代码处理70k jpg文件时,它返回F2。

SUBNOTE the picture im uploading has an extension of .JPG. Could case be a factor? If so, how do i accommodate for that?

注意,我上传的图片的扩展名为. jpg。案例可能是一个因素吗?如果是的话,我该如何适应呢?

7 个解决方案

#1


23  

Note that you might not want to rely on file extensions to determine file type. It would be rather easy for someone to upload an executable file with a .png extension for example. A mime-type can also easily be forged by a malicious client to pass as an image. Relying on that information is a security risk.

注意,您可能不希望依赖文件扩展名来确定文件类型。例如,上传一个扩展名为.png的可执行文件是相当容易的。mime类型也很容易被恶意客户端伪造成图像。依赖这些信息是一种安全风险。

PHP Documentation:
The mime type of the file, if the browser provided this information. An example would be "image/gif". This mime type is however not checked on the PHP side and therefore don't take its value for granted.

PHP文档:如果浏览器提供了这些信息,文件的mime类型。例如“image/gif”。但是,在PHP端不检查这个mime类型,因此不认为它的值是理所当然的。

Try loading the images with gd (getimagesize()) to make sure they are actually valid images (and not just random files pretended with the header of an image file... finfo_file relies on those headers).

尝试使用gd (getimagesize())加载这些图像,以确保它们实际上是有效的图像(而不仅仅是用图像文件的头假装的随机文件……finfo_file依赖于这些头文件)。

if($_FILES["imagefile"]["size"] >= 2120000) {
  echo "F2";
  die();
} else {
    $imageData = @getimagesize($_FILES["imagefile"]["tmp_name"]);

    if($imageData === FALSE || !($imageData[2] == IMAGETYPE_GIF || $imageData[2] == IMAGETYPE_JPEG || $imageData[2] == IMAGETYPE_PNG)) {
      echo "F2";
      die();
    }
}

If you really must use the extension to verify if the file is an image, use strtolower() to put the extension into lowercase.

如果您确实必须使用扩展名来验证文件是否为映像,那么使用strtolower()将扩展名放入小写。

$filecheck = basename($_FILES['imagefile']['name']);
$ext = strtolower(substr($filecheck, strrpos($filecheck, '.') + 1));

if (!(($ext == "jpg" || $ext == "gif" || $ext == "png") && ($_FILES["imagefile"]["type"] == "image/jpeg" || $_FILES["imagefile"]["type"] == "image/gif" || $_FILES["imagefile"]["type"] == "image/png") && 
    ($_FILES["imagefile"]["size"] < 2120000))){
    echo "F2";
    die();
}

#2


5  

SUBNOTE the picture im uploading has an extension of .JPG. Could case be a factor? If so, how do i accommodate for that?

注意,我上传的图片的扩展名为. jpg。案例可能是一个因素吗?如果是的话,我该如何适应呢?

Yes, that is the problem. You should be add strtolower() to this line:

是的,这就是问题所在。您应该将strtolower()添加到这一行:

$ext = substr($filecheck, strrpos($filecheck, '.') + 1);

like:

如:

$ext = strtolower(substr($filecheck, strrpos($filecheck, '.') + 1));

$ext = strtolower(substr($filecheck, strrpos($filecheck, '.) + 1);

That will fix your currently issue. But technically, you shouldn't worry about file extensions, you should really only need to check the MIME type

这将解决您当前的问题。但是从技术上讲,您不应该担心文件扩展,您应该只检查MIME类型

#3


5  

The comparisons like $ext == "jpg" only check that the $ext is exactly "jpg".

像$ext == "jpg"这样的比较只会检查$ext是否就是“jpg”。

You might want to use strtolower on $ext before doing those comparisons, to deal with the ".JPG" situation.

在进行这些比较之前,您可能需要在$ext上使用strtolower来处理“。JPG”情况。


If you are using PHP <= 5.2, you might want to use mime_content_type to check the content-type of the files, instead of relying on $_FILES['imagefile']['name'] and/or $_FILES["imagefile"]["type"], which are both sent by the client -- and can, as such, be faked.

如果您正在使用PHP <= 5.2,您可能希望使用mime_content_type来检查文件的内容类型,而不是依赖于$_FILES['imagefile']['name']和/或$_FILES["imagefile"]["type"],它们都是由客户端发送的,因此可以被伪造。

If you are using PHP >= 5.3, you might want to consider the new extension fileinfo, and it's finfo_file function

如果您正在使用PHP >= 5.3,您可能需要考虑新的扩展fileinfo,它是finfo_file函数。


For the size of the file, you are already using $_FILES["imagefile"]["size"] ; that's OK, I guess, but you will only know it when the file has been uploaded -- still, there is no real way of checking that kind of thing before upload, I'm afraid...

对于文件的大小,您已经在使用$_FILES["imagefile"]["size"];我想这没问题,但你只会在文件上传后才会知道——不过,在上传之前,恐怕没有真正的方法来检查这类东西……


you might be able to find some JS code to do a first pre-check of extension before the file is uploaded -- but you'll still have to check on the server side, as anything done client-side is inherently not secure.

您可能可以找到一些JS代码,以便在文件上传之前对扩展进行第一次预先检查——但是仍然需要在服务器端进行检查,因为客户端所做的任何事情本质上都是不安全的。

Not sure you could do the same about the file's size, though...

不确定您是否可以对文件的大小进行相同的操作…

Some browsers might support a hidden field called MAX_FILE_SIZE (see the documentation about file upload) ; but not sure it is really supported (never seen it used, actually ; so probably isn't :-( )

一些浏览器可能支持一个名为MAX_FILE_SIZE的隐藏字段(请参阅有关文件上传的文档);但不确定它是否真的得到支持(实际上从未见过);所以可能不是:-()


As a sidenote, you will probably want to configure upload_max_filesize, so it allows upload at least as big as what you want (by default, it is generally set to 2MB ; so should already be OK for you)

作为sidenote,您可能希望配置upload_max_filesize,因此它允许上传至少与您想要的大小相同(默认情况下,它通常设置为2MB;所以对你来说应该已经没问题了)

#4


3  

File size is fairly obvious, but what people are doing above to check that it's the right format is somewhat inefficient, and "unsafe".

文件大小是相当明显的,但是人们在上面检查它的正确格式是有些低效和“不安全的”。

Here's what I do:

这是我做的:

if($_FILES["userPicture"]["error"] == 0) {
// File was uploaded ok, so it's ok to proceed with the filetype check.
    $uploaded_type = exif_imagetype($_FILES["userPicture"]["tmp_name"]);
    // What we have now is a number representing our file type.

    switch($uploaded_type) {
        case "1":
            $uploaded_type = "gif";
        break;
        case "2":
            $uploaded_type = "jpg";
        break;
        case "3":
            $uploaded_type = "png";
        break;
    }
}

More info at;
http://www.php.net/manual/en/function.exif-imagetype.php

更多的信息;http://www.php.net/manual/en/function.exif-imagetype.php

Edit: This has the advantage of working "in every browser" because it doesn't rely on the filename, or anything user supplied, except the files array value "error" which tells us there wasn't really an error.

编辑:这具有在“每个浏览器中”工作的优势,因为它不依赖文件名或用户提供的任何内容,除了文件数组值“error”,它告诉我们没有真正的错误。

#5


3  

take note that for Internet Explorer, they submit JPEG file's mime type as image/pjpeg - which is different from other browsers.

注意,对于Internet Explorer,他们将JPEG文件的mime类型提交为image/pjpeg——这与其他浏览器不同。

Here's a simple function to get your mime type against the file extension:

这里有一个简单的函数,可以根据文件扩展名获取mime类型:

function mime2ext($mime){ // mime is like image/jpeg
    $m = explode('/',$mime);
    $mime = $m[count($m)-1]; // get the second part of the mime type
    switch($mime){
        case 'jpg':
        case 'jpeg':
        case 'pjpeg':
            return 'jpg';
            break;
        case 'png':
            return 'png';
            break;
        case 'gif':
            return 'gif';
            break;
    }
    return '';
}

#6


2  

Php is a server side scripting language and if the pictures are at client side, you can't check their size via php before upload.

Php是服务器端脚本语言,如果图片在客户端,在上传之前不能通过Php检查它们的大小。

#7


2  

You need two things:

你需要两件事:

Make your extension check case insensitive:

使您的扩展检查大小写不敏感:

if($strtolower($ext == "jpg")){
  // do your stuff
}

Check if the file actually contains an image. An easy way to do this is fileinfo:

检查文件是否实际包含图像。一个简单的方法是fileinfo:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, $filename);
$finfo_close($finfo);

An alternative way of checking if a file is really an image is loading in an image library like gd. If your file can successfully be loaded, it is an image.

另一种检查文件是否真的是图像的方法是在像gd这样的图像库中加载。如果您的文件可以成功加载,那么它就是一个映像。

Keep in mind that jpeg images can have either the .jpg or the .jpeg extension.

请记住,jpeg图像可以有.jpg或.jpeg扩展。

#1


23  

Note that you might not want to rely on file extensions to determine file type. It would be rather easy for someone to upload an executable file with a .png extension for example. A mime-type can also easily be forged by a malicious client to pass as an image. Relying on that information is a security risk.

注意,您可能不希望依赖文件扩展名来确定文件类型。例如,上传一个扩展名为.png的可执行文件是相当容易的。mime类型也很容易被恶意客户端伪造成图像。依赖这些信息是一种安全风险。

PHP Documentation:
The mime type of the file, if the browser provided this information. An example would be "image/gif". This mime type is however not checked on the PHP side and therefore don't take its value for granted.

PHP文档:如果浏览器提供了这些信息,文件的mime类型。例如“image/gif”。但是,在PHP端不检查这个mime类型,因此不认为它的值是理所当然的。

Try loading the images with gd (getimagesize()) to make sure they are actually valid images (and not just random files pretended with the header of an image file... finfo_file relies on those headers).

尝试使用gd (getimagesize())加载这些图像,以确保它们实际上是有效的图像(而不仅仅是用图像文件的头假装的随机文件……finfo_file依赖于这些头文件)。

if($_FILES["imagefile"]["size"] >= 2120000) {
  echo "F2";
  die();
} else {
    $imageData = @getimagesize($_FILES["imagefile"]["tmp_name"]);

    if($imageData === FALSE || !($imageData[2] == IMAGETYPE_GIF || $imageData[2] == IMAGETYPE_JPEG || $imageData[2] == IMAGETYPE_PNG)) {
      echo "F2";
      die();
    }
}

If you really must use the extension to verify if the file is an image, use strtolower() to put the extension into lowercase.

如果您确实必须使用扩展名来验证文件是否为映像,那么使用strtolower()将扩展名放入小写。

$filecheck = basename($_FILES['imagefile']['name']);
$ext = strtolower(substr($filecheck, strrpos($filecheck, '.') + 1));

if (!(($ext == "jpg" || $ext == "gif" || $ext == "png") && ($_FILES["imagefile"]["type"] == "image/jpeg" || $_FILES["imagefile"]["type"] == "image/gif" || $_FILES["imagefile"]["type"] == "image/png") && 
    ($_FILES["imagefile"]["size"] < 2120000))){
    echo "F2";
    die();
}

#2


5  

SUBNOTE the picture im uploading has an extension of .JPG. Could case be a factor? If so, how do i accommodate for that?

注意,我上传的图片的扩展名为. jpg。案例可能是一个因素吗?如果是的话,我该如何适应呢?

Yes, that is the problem. You should be add strtolower() to this line:

是的,这就是问题所在。您应该将strtolower()添加到这一行:

$ext = substr($filecheck, strrpos($filecheck, '.') + 1);

like:

如:

$ext = strtolower(substr($filecheck, strrpos($filecheck, '.') + 1));

$ext = strtolower(substr($filecheck, strrpos($filecheck, '.) + 1);

That will fix your currently issue. But technically, you shouldn't worry about file extensions, you should really only need to check the MIME type

这将解决您当前的问题。但是从技术上讲,您不应该担心文件扩展,您应该只检查MIME类型

#3


5  

The comparisons like $ext == "jpg" only check that the $ext is exactly "jpg".

像$ext == "jpg"这样的比较只会检查$ext是否就是“jpg”。

You might want to use strtolower on $ext before doing those comparisons, to deal with the ".JPG" situation.

在进行这些比较之前,您可能需要在$ext上使用strtolower来处理“。JPG”情况。


If you are using PHP <= 5.2, you might want to use mime_content_type to check the content-type of the files, instead of relying on $_FILES['imagefile']['name'] and/or $_FILES["imagefile"]["type"], which are both sent by the client -- and can, as such, be faked.

如果您正在使用PHP <= 5.2,您可能希望使用mime_content_type来检查文件的内容类型,而不是依赖于$_FILES['imagefile']['name']和/或$_FILES["imagefile"]["type"],它们都是由客户端发送的,因此可以被伪造。

If you are using PHP >= 5.3, you might want to consider the new extension fileinfo, and it's finfo_file function

如果您正在使用PHP >= 5.3,您可能需要考虑新的扩展fileinfo,它是finfo_file函数。


For the size of the file, you are already using $_FILES["imagefile"]["size"] ; that's OK, I guess, but you will only know it when the file has been uploaded -- still, there is no real way of checking that kind of thing before upload, I'm afraid...

对于文件的大小,您已经在使用$_FILES["imagefile"]["size"];我想这没问题,但你只会在文件上传后才会知道——不过,在上传之前,恐怕没有真正的方法来检查这类东西……


you might be able to find some JS code to do a first pre-check of extension before the file is uploaded -- but you'll still have to check on the server side, as anything done client-side is inherently not secure.

您可能可以找到一些JS代码,以便在文件上传之前对扩展进行第一次预先检查——但是仍然需要在服务器端进行检查,因为客户端所做的任何事情本质上都是不安全的。

Not sure you could do the same about the file's size, though...

不确定您是否可以对文件的大小进行相同的操作…

Some browsers might support a hidden field called MAX_FILE_SIZE (see the documentation about file upload) ; but not sure it is really supported (never seen it used, actually ; so probably isn't :-( )

一些浏览器可能支持一个名为MAX_FILE_SIZE的隐藏字段(请参阅有关文件上传的文档);但不确定它是否真的得到支持(实际上从未见过);所以可能不是:-()


As a sidenote, you will probably want to configure upload_max_filesize, so it allows upload at least as big as what you want (by default, it is generally set to 2MB ; so should already be OK for you)

作为sidenote,您可能希望配置upload_max_filesize,因此它允许上传至少与您想要的大小相同(默认情况下,它通常设置为2MB;所以对你来说应该已经没问题了)

#4


3  

File size is fairly obvious, but what people are doing above to check that it's the right format is somewhat inefficient, and "unsafe".

文件大小是相当明显的,但是人们在上面检查它的正确格式是有些低效和“不安全的”。

Here's what I do:

这是我做的:

if($_FILES["userPicture"]["error"] == 0) {
// File was uploaded ok, so it's ok to proceed with the filetype check.
    $uploaded_type = exif_imagetype($_FILES["userPicture"]["tmp_name"]);
    // What we have now is a number representing our file type.

    switch($uploaded_type) {
        case "1":
            $uploaded_type = "gif";
        break;
        case "2":
            $uploaded_type = "jpg";
        break;
        case "3":
            $uploaded_type = "png";
        break;
    }
}

More info at;
http://www.php.net/manual/en/function.exif-imagetype.php

更多的信息;http://www.php.net/manual/en/function.exif-imagetype.php

Edit: This has the advantage of working "in every browser" because it doesn't rely on the filename, or anything user supplied, except the files array value "error" which tells us there wasn't really an error.

编辑:这具有在“每个浏览器中”工作的优势,因为它不依赖文件名或用户提供的任何内容,除了文件数组值“error”,它告诉我们没有真正的错误。

#5


3  

take note that for Internet Explorer, they submit JPEG file's mime type as image/pjpeg - which is different from other browsers.

注意,对于Internet Explorer,他们将JPEG文件的mime类型提交为image/pjpeg——这与其他浏览器不同。

Here's a simple function to get your mime type against the file extension:

这里有一个简单的函数,可以根据文件扩展名获取mime类型:

function mime2ext($mime){ // mime is like image/jpeg
    $m = explode('/',$mime);
    $mime = $m[count($m)-1]; // get the second part of the mime type
    switch($mime){
        case 'jpg':
        case 'jpeg':
        case 'pjpeg':
            return 'jpg';
            break;
        case 'png':
            return 'png';
            break;
        case 'gif':
            return 'gif';
            break;
    }
    return '';
}

#6


2  

Php is a server side scripting language and if the pictures are at client side, you can't check their size via php before upload.

Php是服务器端脚本语言,如果图片在客户端,在上传之前不能通过Php检查它们的大小。

#7


2  

You need two things:

你需要两件事:

Make your extension check case insensitive:

使您的扩展检查大小写不敏感:

if($strtolower($ext == "jpg")){
  // do your stuff
}

Check if the file actually contains an image. An easy way to do this is fileinfo:

检查文件是否实际包含图像。一个简单的方法是fileinfo:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, $filename);
$finfo_close($finfo);

An alternative way of checking if a file is really an image is loading in an image library like gd. If your file can successfully be loaded, it is an image.

另一种检查文件是否真的是图像的方法是在像gd这样的图像库中加载。如果您的文件可以成功加载,那么它就是一个映像。

Keep in mind that jpeg images can have either the .jpg or the .jpeg extension.

请记住,jpeg图像可以有.jpg或.jpeg扩展。