Issac Kelly
Issac Kelly

Reputation: 6359

How do I find the MIME type of a file with PHP?

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?

Upvotes: 49

Views: 115462

Answers (13)

Joshua
Joshua

Reputation: 866

The MIME type 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');

Upvotes: 0

David
David

Reputation: 875

mime_content_type() appears to be the way to go, notwithstanding the previous 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.

Upvotes: 1

Shane
Shane

Reputation: 2057

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 MIME sniffing specification - I believe this is still a draft specification though.

Anyway, using this specification, I was able to implement a MIME sniffer 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.

Upvotes: 10

Andrew
Andrew

Reputation: 528

If you are working with images only and you need a 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.

Upvotes: 8

vizzy
vizzy

Reputation: 15

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 doesn’t use finfo, exec or a deprecated function.

It works well also with remote resources!

Upvotes: -1

Ale
Ale

Reputation: 2022

function get_mime($file) {
  if (function_exists("finfo_file")) {
    $finfo = finfo_open(FILEINFO_MIME_TYPE); // Return MIME type a la the '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 works—mime_content_type is deprecated, finfo is not installed, and shell_exec is not allowed.

Upvotes: 18

Eric_WVGG
Eric_WVGG

Reputation: 2947

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 Unix-like 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.

Upvotes: 23

phatduckk
phatduckk

Reputation: 1795

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

A more general approach would be to use the FileInfo extension from PECL.

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().

Upvotes: 0

Devon
Devon

Reputation: 5784

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.

Upvotes: 1

enobrev
enobrev

Reputation: 22541

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

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

Upvotes: 0

leek
leek

Reputation: 12131

If you are sure you're only ever working with images, you can check out the exif_imagetype() PHP function, which attempts to return the image MIME type.

If you don't mind external dependencies, you can also check out the excellent getID3 library which can determine the MIME type of many different file types.

Lastly, you can check out the mime_content_type() function - but it has been deprecated for the Fileinfo PECL extension.

Upvotes: 51

jhaagsma
jhaagsma

Reputation: 2454

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.

Upvotes: 1

Klemen Tusar
Klemen Tusar

Reputation: 9709

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;
}

Upvotes: 0

Related Questions