Check picture file type and size before file upload in php

后端 未结 7 1563
走了就别回头了
走了就别回头了 2020-12-09 13:41

I have the following code:

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


        
相关标签:
7条回答
  • 2020-12-09 14:11

    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

    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.

    0 讨论(0)
  • 2020-12-09 14:19

    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.

    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.

    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).

    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.

    $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();
    }
    
    0 讨论(0)
  • 2020-12-09 14:21

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

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


    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.

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


    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...


    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.

    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 :-( )


    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)

    0 讨论(0)
  • 2020-12-09 14:25

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

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

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

    like:

    $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

    0 讨论(0)
  • 2020-12-09 14:29

    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:

    $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.

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

    0 讨论(0)
  • 2020-12-09 14:32

    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.

    0 讨论(0)
提交回复
热议问题