[php] How do I find the mime-type of a file with php?

Ok, so I have an index.php file which has to process many different file types. how do I guess the filetype based on the REQUEST_URI.

If I request http://site/image.jpg, and all requests redirect through index.php, which looks like this

<?php
   include('/www/site'.$_SERVER['REQUEST_URI']);
?>

How would I make that work correctly?

Should I test based on the extension of the file requested, or is there a way to get the filetype?

This question is related to php filesystems http-headers content-type

The answer is


I haven't used it, but there's a PECL extension for getting a file's mimetype. The official documentation for it is in the manual.

Depending on your purposes, a file extension can be ok, but it's not incredibly reliable since it's so easily changed.


The mime of any file on your server can be gotten with this

<?php
function get_mime($file_path){
  $finfo = new finfo(FILEINFO_MIME_TYPE);
  $type  = $finfo->file(file_path);
}

$mime = get_mime('path/to/file.ext');

mime_content_type() appears to be the way to go, notwithstanding the above comments saying it is deprecated. It is not -- or at least this incarnation of mime_content_type() is not deprecated, according to http://php.net/manual/en/function.mime-content-type.php. It is part of the FileInfo extension, but the PHP documentation now tells us it is enabled by default as of PHP 5.3.0.


According to the php manual, the finfo-file function is best way to do this. However, you will need to install the FileInfo PECL extension.

If the extension is not an option, you can use the outdated mime_content_type function.


If you run Linux and have the extension you could simply read the MIME type from /etc/mime.types by making a hash array. You can then store that in memory and simply call the MIME by array key :)

/**
 * Helper function to extract all mime types from the default Linux /etc/mime.types
 */
function get_mime_types() {
    $mime_types = array();
    if (
        file_exists('/etc/mime.types') &&
        ($fh = fopen('/etc/mime.types', 'r')) !== false
    ) {
        while (($line = fgets($fh)) !== false) {
            if (!trim($line) || substr($line, 0, 1) === '#') continue;
            $mime_type = preg_split('/\t+/', rtrim($line));
            if (
                is_array($mime_type) &&
                isset($mime_type[0]) && $mime_type[0] &&
                isset($mime_type[1]) && $mime_type[1]
            ) {
                foreach (explode(' ', $mime_type[1]) as $ext) {
                    $mime_types[$ext] = $mime_type[0];
                }
            }
        }
        fclose($fh);
    }
    return $mime_types;
}

If you are working with Images only and you need mime type (e.g. for headers), then this is the fastest and most direct answer:

$file = 'path/to/image.jpg';
$image_mime = image_type_to_mime_type(exif_imagetype($file));

It will output true image mime type even if you rename your image file


function get_mime($file) {
  if (function_exists("finfo_file")) {
    $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
    $mime = finfo_file($finfo, $file);
    finfo_close($finfo);
    return $mime;
  } else if (function_exists("mime_content_type")) {
    return mime_content_type($file);
  } else if (!stristr(ini_get("disable_functions"), "shell_exec")) {
    // http://stackoverflow.com/a/134930/1593459
    $file = escapeshellarg($file);
    $mime = shell_exec("file -bi " . $file);
    return $mime;
  } else {
    return false;
  }
}

For me, nothing of this does work - mime_content_type is deprecated, finfo is not installed, and shell_exec is not allowed.


mime_content_type() is deprecated, so you won't be able to count on it working in the future. There is a "fileinfo" PECL extension, but I haven't heard good things about it.

If you are running on a *nix server, you can do the following, which has worked fine for me:

$file = escapeshellarg( $filename );
$mime = shell_exec("file -bi " . $file);
$filename should probably include the absolute path.

i got very good results using a user function from http://php.net/manual/de/function.mime-content-type.php @''john dot howard at prismmg dot com 26-Oct-2009 03:43''

function get_mime_type($filename, $mimePath = '../etc') { ...

which doesnt use finfo, exec or deprecated function

works well also with remote ressources!


I actually got fed up by the lack of standard MIME sniffing methods in PHP. Install fileinfo... Use deprecated functions... Oh these work, but only for images! I got fed up of it, so I did some research and found the WHATWG Mimesniffing spec - I believe this is still a draft spec though.

Anyway, using this specification, I was able to implement a mimesniffer in PHP. Performance is not an issue. In fact on my humble machine, I was able to open and sniff thousands of files before PHP timed out.

Here is the MimeReader class.

require_once("MimeReader.php");

$mime = new MimeReader(<YOUR FILE PATH>);
$mime_type_string = $mime->getType();     // "image/jpeg" etc.

if you're only dealing with images you can use the [getimagesize()][1] function which contains all sorts of info about the image, including the type.

A more general approach would be to use the FileInfo extension from PECL. The PHP documentation for this extension can be found at: http://us.php.net/manual/en/ref.fileinfo.php

Some people have serious complaints about that extension... so if you run into serious issues or cannot install the extension for some reason you might want to check out the deprecated function mime_content_type()


You can use finfo to accomplish this as of PHP 5.3:

<?php
$info = new finfo(FILEINFO_MIME_TYPE);
echo $info->file('myImage.jpg');
// prints "image/jpeg"

The FILEINFO_MIME_TYPE flag is optional; without it you get a more verbose string for some files; (apparently some image types will return size and colour depth information). Using the FILEINFO_MIME flag returns the mime-type and encoding if available (e.g. image/png; charset=binary or text/x-php; charset=us-ascii). See this site for more info.


Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to filesystems

Get an image extension from an uploaded file in Laravel Notepad++ cached files location No space left on device How to create a directory using Ansible best way to get folder and file list in Javascript Exploring Docker container's file system Remove directory which is not empty GIT_DISCOVERY_ACROSS_FILESYSTEM not set Trying to create a file in Android: open failed: EROFS (Read-only file system) Node.js check if path is file or directory

Examples related to http-headers

Set cookies for cross origin requests Adding a HTTP header to the Angular HttpClient doesn't send the header, why? Passing headers with axios POST request What is HTTP "Host" header? CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response Using Axios GET with Authorization Header in React-Native App Axios get access to response header fields Custom header to HttpClient request Send multipart/form-data files with angular using $http Best HTTP Authorization header type for JWT

Examples related to content-type

Passing headers with axios POST request Spring MVC 4: "application/json" Content Type is not being set correctly What are all the possible values for HTTP "Content-Type" header? New lines (\r\n) are not working in email body HTML Input="file" Accept Attribute File Type (CSV) How do you set the Content-Type header for an HttpClient request? Utility of HTTP header "Content-Type: application/force-download" for mobile? Set Content-Type to application/json in jsp file Cannot set content-type to 'application/json' in jQuery.ajax Difference between application/x-javascript and text/javascript content types