How to check the file type in PHP and secure file uploads: it is important to validate MIME types in PHP. Especially of files uploaded through an upload form to your website. Using PHP, the best way to validate MIME types is with the PHP extension Fileinfo. Any other method might not be as good or secure as you might think…

PHP file input validation, The old^Wwrong way

It is quite common to only look at the file extension to determine what type of file it is (I was hoping to say “years and years ago”, but unfortunately I still see this on a regular basis…).

An image always has an extension like .jpg, .jpeg, .png or .gif, right? And a Portable Document Format is the only file type to use .pdf as extension. Oh we were wrong!

To validate a file’s extension, we used to use something in the line of:

if( eregi( "\.jpg|\.jpeg|\.gif|\.png|\.bmp", $_FILES['userfile']['name'] ) != FALSE ) {
	...
	...
}

and whether this example uses ereg, eregi or preg_match doesn’t matter. Seeing an extension like jpg, jpeg, gif, png or bmp made sure these are only images, right? Not!

Validate MIME types with PHP Fileinfo Click To Tweet

Some of us might expanded the validation of PHP uploaded files with an extra check:

Read this too:   Check website availability with PHP and cURL

PHP File Validation, A Better Way To Validate MIME Types , but only for images

A better way to validate MIME types in PHP is:

$imageInfo = getimagesize( $_FILES['userfile']['tmp_name'] );
if ( $imageInfo['mime'] == ( "image/png" ) ||
	$imageInfo['mime'] == ( "image/jpeg" ) || 
	$imageInfo['mime'] == ( "image/gif" ) || 
	$imageInfo['mime'] == ( "image/psd" ) || 
	$imageInfo['mime'] == ( "image/bmp" ) ) {

This last check uses a PHP image function called getimagesize(). So this only works on images.

The getimagesize() function will determine the size of any given image file and return the dimensions along with the file type and a height/width text string to be used inside a normal HTML IMG tag and the correspondent HTTP content type.

But getimagesize() only works for images and fails on other file types. Therefore a lot of developers use (hopefully used to use?) mime_content_type().

Well, let that function be deprecated in favor of the PECL extension Fileinfo. And on its turn, the PECL extension Fileinfo now is deprecated in favor of the PHP extension Fileinfo. Can you still follow?

So it is best to use the PHP extension Fileinfo, because it works for other file types than images too.

PHP Fileinfo extension: validate MIME types and secure file uploads in PHP

To properly validate MIME-types in PHP, in order to provide some sort of file upload security, you need to use PHP Fileinfo functions. This can validate Office MIME types and others.

Read this too:   Minify WP-Super-Cache HTML cache files: WPSCMin a WP-Super-Cache plugin

An example PHP function to validate Office and PDF MIME types is:

<?php
/*
 * Follow me on Twitter: @HertogJanR, https://twitter.com/hertogjanr
 */
function check_doc_mime( $tmpname ) {
	// MIME types: http://filext.com/faq/office_mime_types.php
	$finfo = finfo_open( FILEINFO_MIME_TYPE );
	$mtype = finfo_file( $finfo, $tmpname );
	finfo_close( $finfo );
	if( $mtype == ( "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ) || 
		$mtype == ( "application/vnd.ms-excel" ) ||
		$mtype == ( "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) || 
		$mtype == ( "application/vnd.ms-powerpoint" ) ||
		$mtype == ( "application/vnd.openxmlformats-officedocument.presentationml.presentation" ) || 
		$mtype == ( "application/pdf" ) ) {
        return TRUE;
    }
    else {
        return FALSE;
    }
}

if( function_exists( "check_doc_mime" ) ) {
	if ( !check_doc_mime( $_FILES['userfile']['tmp_name'] ) ) {
		/*
		 * Not a MIME type we want uploaded to our site, stop here
		 * and return an error message, or just die();
		 */
	} else {
		/*
		 * a MIME type we support is uploaded. Continue with our
		 * upload script
		 */
	}
}

/* Support https://www.paypal.me/jreilink , thank you! */
?>

This function can be used to verify the MIME type of files uploaded through HTTP $_POST. Proper user input validation is important for your website security!

11 replies
  1. Ingus
    Ingus says:

    Hello, i found an issue it seems. .. I m making update with your function “check_doc_mime()” well it works but makes interesting issue. If i try to upload low size PDF it works but if i try to upload over 2MB it fails to validate! What could be wrong here? (i do not have any size limitations)

    Thanks!

    Reply
    • Ingus
      Ingus says:

      I did found out that big sized PDF $_FILES[‘file’][‘tmp_name’] was returned mime type as text/html but $_FILES[‘file’][‘type’] says it is application/pdf. ..

      Reply
      • Jan Reilink
        Jan Reilink says:

        Hi Ignus,
        Thank you for your commands and sorry I couldn’t reply sooner. Does the “error segment” of the file array provide any insights? You should be able to query $_FILES[‘userfile’][‘error’].

        Reply
  2. bastilol
    bastilol says:

    It seems that your function “check_doc_mime” doesn’t close your finfo, in both cases it returns before closing.

    Reply
      • kevon
        kevon says:

        Good night, there is no echo to know if the file was uploaded or not, also there is no uploads folder to upload anything to. I looked in my php tmp folder but the file wasn’t there either.

        Reply
        • Jan Reilink
          Jan Reilink says:

          Hi Kevon,
          It’s example code, which you can use to build upon. It’s not ready to use, but meant to show you how it can work.

          Reply
          • kevon
            kevon says:

            I am building a portal and need help i’m getting pieces of code but not the full thing. will you be able to assist me with my file upload page. I can upload any file and it even has validation for if the file already exists, what i need is just to limit the filetype to documents only. When i place your code into my code, I dont get a error message and i am still able to upload any file it’s as if it just skips over your code. Can you help? and if so where can I send my code for review?

          • kevon
            kevon says:

            i’m not trying to take advantage of you, Im just from a poor country trying to build web apps so I can make something and get out of the poor country. I guess thats why the saying goes the poorer gets poorer and the rich gets richer. Thanks for the “free advice”.

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *