PHP: Check (validate) if the Uploaded File is an Image

Posted on September 24, 2008, under PHP 

In this tutorial I will show you how to create an image validator script. You can choose between 2 methods of validation: one that will verify if the file is actually an image, by checking the file’s mime-type, and the other one which checks the extension of the uploaded file.

Let’s start creating the configuration file:

config.php

<?php
/* 
1 = Check if the file uploaded is actually an image no matter what extension it has
2 = The uploaded files must have a specific image extension
*/

$validation_type = 1;

if($validation_type == 1)
{
	$mime = array('image/gif' => 'gif',
                  'image/jpeg' => 'jpeg',
                  'image/png' => 'png',
                  'application/x-shockwave-flash' => 'swf',
                  'image/psd' => 'psd',
                  'image/bmp' => 'bmp',
                  'image/tiff' => 'tiff',
                  'image/tiff' => 'tiff',
                  'image/jp2' => 'jp2',
                  'image/iff' => 'iff',
                  'image/vnd.wap.wbmp' => 'bmp',
                  'image/xbm' => 'xbm',
                  'image/vnd.microsoft.icon' => 'ico');
}
else if($validation_type == 2) // Second choice? Set the extensions
{
	$image_extensions_allowed = array('jpg', 'jpeg', 'png', 'gif','bmp');
}

$upload_image_to_folder = 'images/';
?>

Now let’s create the form that will help us to upload the file:

<form enctype="multipart/form-data" action="validate_image_upload.php" method="POST">
    
<!-- MAX_FILE_SIZE must be set before the input element -->
<input type="hidden" name="MAX_FILE_SIZE" value="2048000" />

<!-- The name from the $_FILES array is determined by the input name -->
Select an Image: <input name="image_file" type="file" /> 
<input type="submit" value="Upload" />

</form>

Our form will send the data to validate_image_upload.php. Here, the script will check the type of validation. If the file is validated the user will see a successful submission message and the file will be moved in the specified image folder. The uploaded file failed to pass the validation process? In this case, it will be deleted and the script will output an error message.

<?php
// Do not show notice errors
error_reporting (E_ALL ^ E_NOTICE);

if(!empty($_FILES)) // [START FILE UPLOADED]
{
include 'config.php';

$file = $_FILES['image_file'];

$file_name = $file['name'];

$error = ''; // Empty

// Get File Extension (if any)

$ext = strtolower(substr(strrchr($file_name, "."), 1));

Validation #1 – Check if the uploaded file is an image. This is done using the getimagesize() function:

array getimagesize ( string $filename [, array &$imageinfo] )

This function returns an array with specific information regarding the file. To return specific information such as width, height, mime type, channels, the file that is verified should be a valid image. If $file_info is empty, then the uploaded file is not an image.

We will detect the image’s mime type and we will use this information to add the correct extension to the file.

// Check for a correct extension. The image file hasn't an extension? Add one

   if($validation_type == 1)
   {
   $file_info = getimagesize($_FILES['image_file']['tmp_name']);

      if(empty($file_info)) // No Image?
      {
      $error .= "The uploaded file doesn't seem to be an image.";
      }
      else // An Image?
      {
      $file_mime = $file_info['mime'];

         if($ext == 'jpc' || $ext == 'jpx' || $ext == 'jb2')
         {
         $extension = $ext;
         }
         else
         {
         $extension = ($mime[$file_mime] == 'jpeg') ? 'jpg' : $mime[$file_mime];
         }

         if(!$extension)
         {
         $extension = '';
         $file_name = str_replace('.', '', $file_name);
         }
	  }
   }

Validation #2 – Check the extension of the uploaded file

We’ll use in_array() to determine if the filename’s extension can be found in our list with extensions from config.php. If the extension is not on the list, an error message would be generated notifying the user that the uploaded file’s extension is not an accepted one.

   else if($validation_type == 2)
   {
	  if(!in_array($ext, $image_extensions_allowed))
	  {
	  $exts = implode(', ',$image_extensions_allowed);
	  $error .= "You must upload a file with one of the following extensions: ".$exts;
	  }

	  $extension = $ext;
   }

If no errors were found, copy the file to the specified folder ($upload_image_to_folder) and show a successful submission message to the user.


   if($error == "") // No errors were found?
   {
   $new_file_name = strtolower($file_name);
   $new_file_name = str_replace(' ', '-', $new_file_name);
   $new_file_name = substr($new_file_name, 0, -strlen($ext));
   $new_file_name .= $extension;
   
   // File Name
   $move_file = move_uploaded_file($file['tmp_name'], $upload_image_to_folder.$new_file_name);

   if($move_file)
	   {
	   $done = 'The image has been uploaded.';
	   }
   }
   else
   {
   @unlink($file['tmp_name']);
   }

   $file_uploaded = true;
} // [END FILE UPLOADED]
?>

Check the complete validate_image_upload.php file which has the HTML Form and the Validator:

validate_image_upload.php

<?php
// Do not show notice errors
error_reporting (E_ALL ^ E_NOTICE);

if(!empty($_FILES)) // [START FILE UPLOADED]
{
include 'config.php';

$file = $_FILES['image_file'];

$file_name = $file['name'];

$error = ''; // Empty

// Get File Extension (if any)

$ext = strtolower(substr(strrchr($file_name, "."), 1));

// Check for a correct extension. The image file hasn't an extension? Add one

   if($validation_type == 1)
   {
   $file_info = getimagesize($_FILES['image_file']['tmp_name']);

      if(empty($file_info)) // No Image?
      {
      $error .= "The uploaded file doesn't seem to be an image.";
      }
      else // An Image?
      {
      $file_mime = $file_info['mime'];

         if($ext == 'jpc' || $ext == 'jpx' || $ext == 'jb2')
         {
         $extension = $ext;
         }
         else
         {
         $extension = ($mime[$file_mime] == 'jpeg') ? 'jpg' : $mime[$file_mime];
         }

         if(!$extension)
         {
         $extension = '';
         $file_name = str_replace('.', '', $file_name);
         }
	  }
   }
   else if($validation_type == 2)
   {
	  if(!in_array($ext, $image_extensions_allowed))
	  {
	  $exts = implode(', ',$image_extensions_allowed);
	  $error .= "You must upload a file with one of the following extensions: ".$exts;
	  }

	  $extension = $ext;
   }

   if($error == "") // No errors were found?
   {
   $new_file_name = strtolower($file_name);
   $new_file_name = str_replace(' ', '-', $new_file_name);
   $new_file_name = substr($new_file_name, 0, -strlen($ext));
   $new_file_name .= $extension;
   
   // File Name
   $move_file = move_uploaded_file($file['tmp_name'], $upload_image_to_folder.$new_file_name);

   if($move_file)
	   {
	   $done = 'The image has been uploaded.';
	   }
   }
   else
   {
   @unlink($file['tmp_name']);
   }

   $file_uploaded = true;
} // [END FILE UPLOADED]
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
 <head>
  <title>Validate Image on Upload @ BitRepository.com</title>
  <meta name="Author" content="BitRepository.com">

  <meta name="Keywords" content="validate, image, upload, post, files">
  <meta name="Description" content="How to check if an uploaded file is an image">
 </head>

 <body>

<center>

 <?php
 if($file_uploaded)
 {
	 if($done)
	 {
	 echo '<font color="green">'.$done.'</font>';
	 }
	 else if($error)
	 {
	 echo '<font color="red">'.$error.'</font>';
	 }
	 echo '<br /><br />';
 }
 ?>

<form enctype="multipart/form-data" action="validate_image_upload.php" method="POST">
    
<!-- MAX_FILE_SIZE must be set before the input element -->
<input type="hidden" name="MAX_FILE_SIZE" value="2048000" />

<!-- The name from the $_FILES array is determined by the input name -->
Select an Image: <input name="image_file" type="file" /> <input type="submit" value="Upload" />

</form>

</center>

 </body>
</html>

NOTE Please make sure the config.php file is located in the same folder with validate_image_upload.php, and the folder where the image file will be moved is writable.


Comment via Facebook

comments

21 Replies to "PHP: Check (validate) if the Uploaded File is an Image"

  1. what u can help for this ,i`m upload crocus.gif today at 19:32 i that file have comand inside
    en demo page no have problemas why?

  2. I don’t understand you 100%. Are you having problems uploading an image or that image isn’t recognized?

  3. how to validate the file name will occur in this code:

    function validate()
    {
    if(isset(“./upload/”.$HTTP_POST_FILES[‘file’][‘name’] == $HTTP_POST_FILES[‘file’][‘tmp_name’]))
    {
    alert(“the file has been already placed”);
    }
    else
    {
    alert(“the file has been upload successfully”);
    }
    }

  4. This isn’t the right way to do it! Also, you should use $_FILES instead of $HTTP_POST_FILES (that is for earlier PHP Versions lower than 4.1.0).

  5. Why just check the file extension, when someone could upload something else, with the extension changed.

    Divide the image width or height, as you cannot divide by zero.

  6. Then just use the first validation type. I've added the extension checker just in case someone is interested in it, because I've seen many scripts that use it. Anyway, why someone would bother to upload something else with the extension changed? The file has an image extension and if, for instance, is a PHP file, it cannot be executed and the webmaster will notice that this is not an image because it won't load. However, to avoid such things, I recommend using the first validator that checks if the file is an image, without taking into consideration the extension.

  7. Thanks, this helped alot! :)

  8. thank u much….
    is very helpful to me..

  9. Thanks! It is helpful.

  10. The reason why most utilities do an extension check rather than a mime type check is because mime-types are set by the browser uploading the file, not the server itself. Thus, a would-be hacker can upload a php file, declaring it to be the mime type of image/jpeg.

    Although, looking at your code, you do deal with this problem fairly successfully, stripping off the old file extension and replacing it with the declared file extension. That is an interesting way to untaint.

    But otherwise, you cannot trust that the mime-type and the file extension agree.

  11. In php image upload validation you cannot always depend on the mime type being correct. Good idea about dividing width and height attributes though.

  12. okay this look really good. But I do not know what to do with it other than to put it in my folder. How can I make this work with a php page that I have. For instance I would like the uploader to be on a page that people can upload picture and for the picture to go to my database name “recipe” from the table “recipes” under the “picture” column.

    Do I need to change any of your code to do this?

  13. This was really great. This could really helpful for my coming project.. Thanx a lot.

  14. This is just client side check. Client can fake all of this.

    -Better solution is to process image with GD, or imageshack so you can remove all unwanted code inside (if it have)…so users can’t upload “executable” images.
    -Change name into some random name and call image with php, so user never know real image path (eg. image.php?i=myimage.jpg).

  15. Thanks for this!

    Very useful!

  16. Nice, but I would prefer a function like this:

    function imageIsValid($path) {
    if (filesize($path) < 700000) { // must be larger than 700K, for example
    if (in_array(exif_imagetype($path), array(IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF))) {
    return true;
    }
    }

    return false;
    }

    And exif.dll must be enabled in php.ini.

    Happy coding.

  17. Nice, but I would prefer a function like this:


    function imageIsValid($path) {
    if (filesize($path) < 700000) { // must be larger than 700K, for example
    if (in_array(exif_imagetype($path), array(IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF))) {
    return true;
    }
    }

    return false;
    }

    And exif.dll must be enabled in php.ini.

    Happy coding.

  18. I found a post that shows that you can insert malicious php code in a image file and it will still be a valid image file. http://ha.ckers.org/blog/20070604/passing-malicious-php-through-getimagesize/

  19. Hey Gabe,

    How are you, it’s been a long time? We can chat via email, but I wanted to support your site here, and by the way it is looking great!

    So to get to the point, I finally took the initiative to study PHP and get it under my belt. I am still in the beginning stages and ran into a problem with my mime type validation. Everything is working perfectly, but when I upload a .avi file, it doesn’t display an error for the file type or the file size. I am working on both a local server and remote server. Also, when I upload a jpg that is 1.4 mb (my upload limit is set to 50kb), I get the right error displayed and all the other errors as well. I want to post all the code here (2 files (1 w/ 159 lines, 2 w/ 47 lines)) just so you can see everything is written correctly. Let me know if that is ok, or if I should send you the files.

    Also, I am looking forward to becoming a member and adding to the conversations here.

    1. Greetings,

      Long time, no chat indeed. Send me the files via email. I’ll take a look at them ;)

  20. i have one problem.While updating profile i dont want to change my image but when i click on submit button my image field will be blank please help me

Leave a Reply


* = required fields

  (will not be published)


XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Note: If you want to post CODE Snippets, please make them postable first!
(e.g. <br /> should be converted to &lt;br /&gt;)

POSTING RULES:

  • The comment must be relevant with the topic of the post.
  • Only comments with real email addresses will get approved. So, emails like 'abc@domain.com' will not be accepted.
  • Do not post the same message in multiple articles through the site.
  • Do not post advertisements, junk mail or pyramid schemes.
  • In case you post a link to another site, please explain briefly where the link goes as a courtesy to other users.
  • Do not post comments such as: "Thank you", "Awesome", "Nice tutorial", "Merci", etc.