How do I determine the extension(s) associated with a MIME type in PHP?

24,986

Solution 1

Not built-in, but it's not terribly hard to roll your own:

function system_extension_mime_types() {
    # Returns the system MIME type mapping of extensions to MIME types, as defined in /etc/mime.types.
    $out = array();
    $file = fopen('/etc/mime.types', 'r');
    while(($line = fgets($file)) !== false) {
        $line = trim(preg_replace('/#.*/', '', $line));
        if(!$line)
            continue;
        $parts = preg_split('/\s+/', $line);
        if(count($parts) == 1)
            continue;
        $type = array_shift($parts);
        foreach($parts as $part)
            $out[$part] = $type;
    }
    fclose($file);
    return $out;
}

function system_extension_mime_type($file) {
    # Returns the system MIME type (as defined in /etc/mime.types) for the filename specified.
    #
    # $file - the filename to examine
    static $types;
    if(!isset($types))
        $types = system_extension_mime_types();
    $ext = pathinfo($file, PATHINFO_EXTENSION);
    if(!$ext)
        $ext = $file;
    $ext = strtolower($ext);
    return isset($types[$ext]) ? $types[$ext] : null;
}

function system_mime_type_extensions() {
    # Returns the system MIME type mapping of MIME types to extensions, as defined in /etc/mime.types (considering the first
    # extension listed to be canonical).
    $out = array();
    $file = fopen('/etc/mime.types', 'r');
    while(($line = fgets($file)) !== false) {
        $line = trim(preg_replace('/#.*/', '', $line));
        if(!$line)
            continue;
        $parts = preg_split('/\s+/', $line);
        if(count($parts) == 1)
            continue;
        $type = array_shift($parts);
        if(!isset($out[$type]))
            $out[$type] = array_shift($parts);
    }
    fclose($file);
    return $out;
}

function system_mime_type_extension($type) {
    # Returns the canonical file extension for the MIME type specified, as defined in /etc/mime.types (considering the first
    # extension listed to be canonical).
    #
    # $type - the MIME type
    static $exts;
    if(!isset($exts))
        $exts = system_mime_type_extensions();
    return isset($exts[$type]) ? $exts[$type] : null;
}

Solution 2

You could use mime_content_type but it is deprecated. Use fileinfo instead:

function getMimeType($filename) {
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $filename);
    finfo_close($finfo);
    return $mime;
}

Solution 3

You might want to use this library: https://github.com/ralouphie/mimey

Example usage:

$mimes = new \Mimey\MimeTypes;

// Convert extension to MIME type:
$mimes->getMimeType('json'); // application/json

// Convert MIME type to extension:
$mimes->getExtension('application/json'); // json

This because apparently the quality of the provided PHP functions is dubious.

Solution 4

If you are working with vary limited extensions of images and need something very simple, I think this is enough.

   switch($info['mime'])
   {
    case 'image/gif'    : $extension = 'gif';   break;
    case 'image/png'    : $extension = 'png';   break;
    case 'image/jpeg'   : $extension = 'jpg';   break;

    default :
        throw new ApplicationException('The file uploaded was not a valid image file.');
    break;
    }
Share:
24,986

Related videos on Youtube

Alexander Trauzzi
Author by

Alexander Trauzzi

Experienced full-stack developer and conference presenter with extensive knowledge in open source, software architecture and design patterns. Accomplishments range from defining company technical direction and leading teams to success while creating APIs and server-side infrastructure for mobile apps. Many of my interests center around software, spending my free time expanding my skills and learning new technologies.

Updated on September 28, 2020

Comments

  • Alexander Trauzzi
    Alexander Trauzzi over 3 years

    Is there a quick and dirty mapping of MIME types to extensions in PHP that I can make use of?

    • Mark Amery
      Mark Amery about 10 years
      People merely wanting to map extensions to MIME types, rather than the other way round, should note that there is now built-in support for this which they should take advantage of - see Jorge's answer rather than the accepted one.
    • Wranorn
      Wranorn over 6 years
      @MarkAmery however as noted, finfo_file() requires that the file exists. Which isn't always the case. Chaos' answer is still more on point to the OP and still valid 8 years later.
  • Jorge Barata
    Jorge Barata over 10 years
    I think this is an old answer. Now you should use fileinfo php.net/manual/en/ref.fileinfo.php
  • Mark Amery
    Mark Amery about 10 years
    It's worth noting that the OP actually asked to map MIME types to file extensions. This still covers the most common use case (and probably the one the OP was faced with), so it certainly deserves to exist and I've +1ed it, but it's not strictly an answer to the question that was asked as pedantically interpreted.
  • Pang
    Pang almost 10 years
    Note: finfo_file() and mime_content_type() requires that file exists.
  • danronmoon
    danronmoon over 9 years
    @JorgeB.G. That requires that the file exists, doesn't it?
  • Qix - MONICA WAS MISTREATED
    Qix - MONICA WAS MISTREATED over 9 years
    @danronmoon. yes it does.
  • Greg
    Greg almost 8 years
    Where does it say that it is deprecated?
  • kloddant
    kloddant almost 3 years
    This fails unless $filename is a string that it can read. It does not work on generic strings that do not correspond to files on the server.
  • Mouagip
    Mouagip almost 3 years
    I wrote a small package to guess the MIME type based on the file extension (if the file does not exist or cannot be accessed): github.com/mzur/guess-mime