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

时间:2009-08-08 21:25:46

标签: php

我有以下代码:

$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();
}

我需要做的是检查上传的文件是jpg / gif / png还是小于2 megs。

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

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

笔记本都 图片即时上传的扩展名为.JPG。案件可能是一个因素吗?如果是这样,我该如何适应呢?

7 个答案:

答案 0 :(得分:22)

请注意,您可能不希望依赖文件扩展名来确定文件类型。例如,某人上传具有.png扩展名的可执行文件相当容易。恶意客户端也可以轻易伪造mime-type作为图像传递。 依赖该信息存在安全风险

  

PHP Documentation:
  文件的mime类型,如果浏览器提供了此信息。一个例子是“image / gif”。但是,在PHP方面没有检查这个mime类型,因此不会将其值视为理所当然

尝试使用gdgetimagesize())加载图片,以确保它们实际上是有效图像(而不仅仅是假装有图像文件标题的随机文件... 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();
    }
}

如果您确实必须使用扩展程序来验证文件是否为图片,请使用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();
}

答案 1 :(得分:5)

  

SUBNOTE图片即时上传的扩展名为.JPG。案件可能是一个因素吗?如果是这样,我该如何适应呢?

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

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

像:

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

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

答案 2 :(得分:5)

$ext == "jpg"之类的比较只会检查$ext是否完全是“jpg”。

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


如果您使用的是PHP&lt; = 5.2,则可能需要使用mime_content_type来检查文件的内容类型,而不是依赖$_FILES['imagefile']['name']和/或$_FILES["imagefile"]["type"]两者都是由客户发送的 - 因此可以伪造。

如果您使用的是PHP&gt; = 5.3,则可能需要考虑新的扩展程序fileinfo,并且它是finfo_file函数


对于文件的大小,您已经在使用$_FILES["imagefile"]["size"];没错,我猜,但是你只会在上传文件时才知道 - 但是,在上传之前没有真正的方法来检查那种东西,我担心......


您可能能够找到一些JS代码在文件上传之前对扩展进行首次预检 - 但您仍然需要检查服务器端,因为客户端的任何操作本质上都不安全。 / p>

不确定你可以对文件的大小做同样的事情,但是......

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


作为旁注,您可能希望配置upload_max_filesize,因此它允许上传至少与您想要的一样大(默认情况下,它通常设置为2MB;所以应该已经适合您)

答案 3 :(得分:3)

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

这是一个简单的函数,可以根据文件扩展名获取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 '';
}

答案 4 :(得分:3)

文件大小相当明显,但是上面人们在做什么检查它是正确的格式效率有点低,而且“不安全”。

这就是我的所作所为:

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;
    }
}

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

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

答案 5 :(得分:2)

Php是一种服务器端脚本语言,如果图片位于客户端,则无法通过php 检查其大小上传。

答案 6 :(得分:2)

你需要两件事:

使您的扩展程序检查不区分大小写:

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

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

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

检查文件是否真的是图像的另一种方法是加载到像gd这样的图像库中。如果您的文件可以成功加载,则为图像。

请注意,jpeg图片可以包含.jpg.jpeg扩展名。