我是一名 PHP 初学者,目前正在学习“验证文件上传”部分。
我制作了一个包含以下代码的 test.php 页面:
var_dump(@$_FILES['file']['type']);
首先,我上传了一张图片“img.gif”,它返回了:
string 'image/gif' (length=9)
然后,我将图像的扩展名更改为“.jpg”并返回:
string 'image/jpeg' (length=10)
所以我意识到 $_FILES["file"]["type"] 只返回上传的文件扩展名,但实际上并没有检查它是什么文件。
在这个页面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))
我想知道为什么上面的代码检查文件扩展名两次?我从上面的代码中删除了一些,这是我的新代码:
$allowedExts = array("gif", "jpeg", "jpg", "png");
$extension = end(explode(".", $_FILES["file"]["name"]));
if (($_FILES["file"]["size"] < 20000) && in_array($extension, $allowedExts))
我的代码正确吗?或者你有什么更好的方法来验证上传文件是图像吗?
谢谢!
您应该将文件※的
tmp_name
传递给getimagesize
,它将为您提供图像的大小和类型(如果是图像)。如果传递的参数是文件而不是图像,它将返回 false,这将允许您进行验证。
※:我的意思是上传后创建的临时文件。
例如:
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
}
}
此代码使用 file_exists 只是为了通用。如果没有上传文件,您将获得
$_FILES['file']['size'] = 0
、$_FILES['file']['tmp_name'] = ''
和 $_FILES['file']['error'] = 4
。另请参阅is_可读。有关错误值,请参阅php.net的文件上传错误解释。
注意: 正如评论中指出的,上面的代码检查文件上传是否是图像,但不检查是否安全。请参阅:PHP 图像上传安全性:如何不这样做。
$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))
这会检查两次,因为文件的扩展名和“文件类型”可能不同,因此有人无法上传扩展名为 .png 的可执行文件。
在修改后的代码中,可以上传具有修改后的扩展名的不同类型的文件。就像他们可以上传带有“.png”扩展名的 Word 文档。
您的新代码只是检查扩展名,没有双重检查。
您的新代码仅检查文件的扩展名和文件的大小。它不检查文件的类型。
我强烈建议使用您的旧代码,因为它还会检查文件类型。