PHP Check File Download

I am starting PHP and am currently studying the part "Checking File Upload".

I made a test.php page containing the following code:

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

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

 string 'image/gif' (length=9) 

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

 string 'image/jpeg' (length=10) 

So, I realized that $ _FILES ["file"] ["type"] returns only the extension of the downloaded file, but did not really check what the file was.

On this page http://www.w3schools.com/php/php_file_upload.asp there is 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 am wondering why the above codes check the file extension twice? I deleted some of the previous 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 check the download file - is this an image?

Thanks!

+8
source share
3 answers

You should pass the tmp_name of the * file to getimagesize , it will give you the size and type of the image (if it is an image). If the argument passed is a file but not an image, it returns false, which allows you to check.

Edit: The only reliable way to validate an image is to make a copy of it with GD or Imagick - getimagesize can be easily hacked .

*: I mean, a temporary file created after loading.

For example:

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

This code uses file_exists just to be shared. If the file has not been uploaded, you will receive $_FILES['file']['size'] = 0 , $_FILES['file']['tmp_name'] = '' and $_FILES['file']['error'] = 4 . See Also is_readable . For error values, see errors when uploading a file to php.net .

+14
source
 $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)) 

This is double checked because the file extension and file type may be different, so someone cannot download the executable file with the extension .png.

In your modified code, you can download a different type of file with a modified extension. for example, they can upload a document with the extension ".png".

Your new code just checks the extension and does not double check.

+2
source

Your new code only checks the file extension and file size. It does not check file type.

I highly recommend using the old code because there it also checks the file type.

0
source

All Articles