PHP验证文件上载

时间:2013-03-24 05:44:16

标签: php image upload pdo

我是一名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))

我的代码是否正确?或者你有更好的方法来验证上传文件是图像吗?

谢谢!

3 个答案:

答案 0 :(得分:15)

您应该将文件*的tmp_name传递给getimagesize,它会为您提供图像的大小和类型(如果是图像)。如果传递的参数是文件而不是图像,则返回false,这将允许您进行验证。

编辑:唯一可靠的图像验证方法是使用GD或Imagick制作副本 - getimagesize can be easily hacked

*:我的意思是,上传后创建的临时文件。

例如:

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_readable。有关错误值,请参阅file upload errors explained上的php.net

答案 1 :(得分:3)

$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文档。

您的新代码只是检查扩展程序而没有仔细检查。

答案 2 :(得分:0)

您的新代码仅检查文件的扩展名和文件大小。它不会检查文件的类型。

我强烈建议您使用旧代码,因为它也会检查文件类型。