PHP, Mime Types and Fileinfo

January 19th, 2006

When uploading files in PHP, its quite common for people to check the MIME type for the file uploaded against an array of allowed mime types. This may seem like common sense, however, its extremely unreliable. The mime type given in the array is the mime type sent by the browser to the script. Most browsers, if not all, determine the mime type based upon the file's extension - which may not reveal the true mime type of the file we are dealing with.

Array
(
    [file] => Array
        (
            [name] => image.png
            [type] => image/png
            [tmp_name] => /tmp/phpWETc9o
            [error] => 0
            [size] => 4604
        )
)

As you can see in the above excerpt from $_FILES, the file uploaded is called image.png and its mime type is image/png. However, this image is actually a JPEG image, which was renamed to image.png.

The true way to determine the mime type of the file is to examine the file's headers. This may seem complicated, but in fact is exceptionally easy with a PECL module called Fileinfo. Fileinfo was developed by Ilia Alshanetsky, one of the key PHP developers.

Most people are unaware of the beauties hiding in PECL and PEAR that can enable you to work more efficiently. PECL extensions are compiled from source code and allows you to use them as if the feature was within PHP itself. If you don't know how, take a look at my guide for installing PECL modules.

After installing Fileinfo, and verifying its presence using phpinfo(); you can get to work of determining file mime types. There are two ways of achieving this in Fileinfo:

Mime Types in PHP 4.x

In order to determine the mime type of a file in PHP 4, the following code can be used:

PHP:
  1. $file = "/www/movie.mpg";
  2. $handle = finfo_open(FILEINFO_MIME);
  3. $mime_type = finfo_file($handle,$file); //gives "video/mpeg"

Note that we pass FILEINFO_MIME when we use finfo_open() which will return the mime type for us. There are several other arguments that can be used when we don't want to determine the mime type, each one separated with a pipe symbol |

  • FILEINFO_PRESERVE_ATIME - if possible preserve the original access time
  • FILEINFO_SYMLINK - follow symlinks
  • FILEINFO_DEVICES - look at the contents of blocks or character special devices
  • FILEINFO_COMPRESS - decompress compressed files
PHP:
  1. $file = "/www/movie.mpg";
  2. $handle = finfo_open(FILEINFO_COMPRESS);
  3. $mime_type = finfo_file($handle,$file); //gives "MPEG sequence, v1, system multiplex"

Mime Types in PHP 5.x

If you use PHP 5, then there is an Object Oriented approach to using Fileinfo:

PHP:
  1. $fi = new finfo(FILEINFO_MIME);
  2. $mime_type = $fi->buffer(file_get_contents($file));

More information on the Fileinfo extension can be found here.

 Add to del.icio.us    Digg this    Technorati

Related Posts:

Entry Filed under: PHP

8 Comments Add your own

  • 1. Ben  |  January 19th, 2006 at 3:06 pm

    Very useful post!

    You can also use mime_content_type() for determining Mime types.

    Its absolutely imperative that your scripts check the mime type of uploaded files, since the $_FILES array's contents is determined by the browser NOT the server. If the user is on MSIE the mime-type is simply picked out by the file extension not the file's headers, leaving a nice big hole for exploitation.

  • 2. Sergio Álvarez (xergio)&hellip  |  February 6th, 2006 at 2:06 am

    Gentoo, PHP5 y mime_content_type()Esto es para recordarlo cuando en un futuro me vuelva a pasar.Quería usar la función mime_content_type() en PHP5, la cual me da el MIME Type de un archivo (vamos, el tipo de archivo que es según el contenido). Pero resulta que en G…

  • 3. Using DirectoryIterator t&hellip  |  May 18th, 2006 at 5:07 pm

    [...] getType() - get file type (not MIME Type) [...]

  • 4. Jason  |  November 1st, 2006 at 11:17 pm

    If you have shell_exec ability, you can also use the following method. I've found it to be as accurate and just as simple.

    //format file path in case it contains strange chars or spaces
    $fileCommandPath = escapeshellarg('/abs/path/to/file.ext');

    //get response from shell "file" command. note use of backtick operator
    $fileCommandResult = trim(`file -bi $fileCommandPath`);

    //sometimes "file -bi" returns extra data with mime type. only use string before ";"
    $fileCommandResult = explode(';', $fileCommandResult);

    //pretty sure the real mime type of the file is...
    $mime_type = $fileCommandResult[0];

  • 5. bart bosma  |  January 23rd, 2007 at 1:03 pm

    I think Jason's shell solution doesn't works in windows, and it's way too much code just to get a 'stupid' mime type :).

    i think the mime_content_type followed by the fileinfo fc. are the best choices..

  • 6. Malversán  |  February 16th, 2007 at 12:47 pm

    $mime_type = $fi->buffer(file_get_contents($file));

    It's a total waste of memory to load file contents into a variable if you're dealing with big files.

    There's an easier solution with the finfo class, although you won't find it in the (always outdated) PHP documentation.

    $mime_type = $fi->file($file);

    In fact it was you who helped me to figure that there was a '->file()' method. I was searching for an example of FileInfo usage and the only one I found was this page.

    Regards.

  • 7. How To Force File Downloa&hellip  |  August 12th, 2007 at 3:16 pm

    [...] Related info Determining MIME type of a file automatically More on determining the MIME type Common MIME types HTTP, caching and other stuff Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages. [...]

  • 8. Generating MIME Type in P&hellip  |  February 14th, 2009 at 5:23 pm

    [...] found a very helpful PHP, Mime Types and Fileinfo post on Jelly and Custard. The "Mime Types in PHP 4.x" seemed to be exactly what I [...]

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Calendar

January 2006
M T W T F S S
« Dec   Feb »
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

Most Recent Posts