PHP 验证文件上传
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15595592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP Validating the File Upload
提问by nut
I'm a PHP beginner and currently learning the "Validating the File Upload" part.
我是一名 PHP 初学者,目前正在学习“验证文件上传”部分。
I made a test.php page containing following code:
我做了一个包含以下代码的 test.php 页面:
var_dump(@$_FILES['file']['type']);
First, I uploaded an image "img.gif" and it returned:
首先,我上传了一张图片“img.gif”并返回:
string 'image/gif' (length=9)
Then, I changed the image's extension to ".jpg" and it returned:
然后,我将图像的扩展名更改为“.jpg”并返回:
string 'image/jpeg' (length=10)
So I realized $_FILES["file"]["type"] only return the uploaded file extension but didn't actually check what file is it.
所以我意识到 $_FILES["file"]["type"] 只返回上传的文件扩展名,但实际上并没有检查它是什么文件。
In this page, http://www.w3schools.com/php/php_file_upload.asp, there is a code:
在这个页面,http://www.w3schools.com/php/php_file_upload.asp,有一段代码:
$allowedExts = array("gif", "jpeg", "jpg", "png");
$extension = end(explode(".", $_FILES["file"]["name"]));
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 20000)
&& in_array($extension, $allowedExts))
I'm wondering why above codes check file extension twice? I deleted some from above codes and this is my new code:
我想知道为什么上面的代码会检查文件扩展名两次?我从上面的代码中删除了一些,这是我的新代码:
$allowedExts = array("gif", "jpeg", "jpg", "png");
$extension = end(explode(".", $_FILES["file"]["name"]));
if (($_FILES["file"]["size"] < 20000) && in_array($extension, $allowedExts))
Is my code correct? Or do you have any better ways to validate the upload file is a image?
我的代码正确吗?或者你有什么更好的方法来验证上传的文件是图片吗?
Thanks!
谢谢!
回答by Theraot
You should pass the tmp_name of the file* to getimagesize, it will give you the size and type of the image (if it is an image). If the passed argument is a file but not an image it returns false, that will allow you to validate.
您应该将文件的 tmp_name* 传递给getimagesize,它将为您提供图像的大小和类型(如果它是图像)。如果传递的参数是文件而不是图像,则它返回 false,这将允许您进行验证。
Edit: The only reliable method of image validation is to make a copy of it using GD or Imagick - getimagesize can be easily hacked.
编辑:图像验证唯一可靠的方法是使用 GD 或 Imagick 制作它的副本 - getimagesize 很容易被黑。
*: I mean, the temporal file created after upload.
*:我的意思是,上传后创建的临时文件。
For example:
例如:
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
$file = $_FILES['file']['tmp_name'];
if (file_exists($file))
{
$imagesizedata = getimagesize($file);
if ($imagesizedata === FALSE)
{
//not image
}
else
{
//image
//use $imagesizedata to get extra info
}
}
else
{
//not file
}
}
This code uses file_existsjust to be general. In case no file were uploaded you would get $_FILES['file']['size'] = 0, $_FILES['file']['tmp_name'] = ''and $_FILES['file']['error'] = 4. See also is_readable. For the error values see file upload errors explainedat php.net.
这段代码使用file_exists只是为了通用。如果没有上传文件,您将获得$_FILES['file']['size'] = 0,$_FILES['file']['tmp_name'] = ''和$_FILES['file']['error'] = 4。另见is_readable。对于误差值看文件上传错误解释在php.net。
回答by Maulik Vora
$allowedExts = array("gif", "jpeg", "jpg", "png");
$extension = end(explode(".", $_FILES["file"]["name"]));
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 20000)
&& in_array($extension, $allowedExts))
This is checked twice because, the extension of the file and 'file type' can be differ, so someone can not upload executable file with .png extension.
这被检查了两次,因为文件的扩展名和“文件类型”可能不同,所以有人不能上传带有 .png 扩展名的可执行文件。
In your modified code, it is possible to upload a different type of file with modified extension. like they can upload word document with '.png' extension.
在您修改的代码中,可以上传具有修改扩展名的不同类型的文件。就像他们可以上传带有“.png”扩展名的word文档一样。
Your new code is just checking extension and don't have double check.
您的新代码只是检查扩展名,没有双重检查。
回答by Yogesh Suthar
Your new code only checks the extension of the file and the size of the file. It doesn't checks the type of the file.
您的新代码仅检查文件的扩展名和文件的大小。它不检查文件的类型。
I will strongly recommend to use your old code because there it checks the file type also.
我强烈建议使用您的旧代码,因为它还会检查文件类型。

