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!
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 passed argument is a file but not an image it returns false, that will allow you to validate.
Edit: The only reliable method of image validation is to make a copy of it using GD or Imagick - getimagesize can be easily hacked.
*: I mean, the temporal file created after upload.
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 general. In case no file were uploaded you would get $_FILES['file']['size'] = 0
, $_FILES['file']['tmp_name'] = ''
and $_FILES['file']['error'] = 4
. See also is_readable. For the error values see file upload errors explained at php.net.
$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 checked twice because, the extension of the file and 'file type' can be differ, so someone can not upload executable file with .png extension.
In your modified code, it is possible to upload a different type of file with modified extension. like they can upload word document with '.png' extension.
Your new code is just checking extension and don't have double check.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With