Search code examples
phpimageupload

PHP Validating the File Upload


I'm a PHP beginner and currently learning the "Validating the File Upload" part.

I made a test.php page containing following code:

var_dump(@$_FILES['file']['type']);

First, I uploaded an image "img.gif" and it returned:

string 'image/gif' (length=9)

Then, I changed the image's extension to ".jpg" and it returned:

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.

In this page, http://www.w3schools.com/php/php_file_upload.asp, there is a code:

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


Solution

  • You could pass the tmp_name of the file to getimagesize, it will give you the size and type of the image (if the first few bytes of that file appears to belong to an image). Otherwise it returns false, that will allow you to validate.

    Besides, you MUST check the extension, of the original filename, because your web-server will judge your file by it, and execute accordingly. And of course a PHP file can fake a few bytes at the top, disguising itself as an image.

    For example:

    if ($_SERVER['REQUEST_METHOD'] === 'POST')
    {
        if ($_FILES['file']['error'] === UPLOAD_ERR_OK)
        {
            // get the ext
            $filename = $_FILES['file']['name'];
            $ext = pathinfo($filename, PATHINFO_EXTENSION);
    
            // get the type
            $tmpfile = $_FILES['file']['tmp_name'];
            $imagesizedata = getimagesize($file);
    
            if (!in_array($ext, $allowed)) { // check the ext
                //not an image
            } elseif ($imagesizedata === FALSE) // check the type
                 //not an image
            } else {
                //image
                //use $imagesizedata to get extra info
            }
        }
    }
    

    For the error values see file upload errors explained at php.net.