35

I am using mime_content_type() in PHP 5.5 to get a MIME type, but it throws fatal: error function not found.

How can I achieve this on PHP 5.5?

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
Jitendra Yadav
  • 896
  • 1
  • 6
  • 14
  • 3
    Would you mind accepting an answer to your question? I know this was asked a while ago, but it'd be nice to know what your solution was in the end, too :) – Erutan409 Nov 25 '15 at 00:58
  • 1
    2017: [This should be the accepted answer](https://stackoverflow.com/a/39335480/114558) – rinogo Aug 29 '17 at 19:07

8 Answers8

60

Make use of the finfo() functions.

A simple illustration:

<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, "path/to/image_dir/image.gif");
finfo_close($finfo);

OUTPUT :

image/gif

Note : Windows users must include the bundled php_fileinfo.dll DLL file in php.ini to enable this extension.

Community
  • 1
  • 1
Shankar Narayana Damodaran
  • 68,075
  • 43
  • 96
  • 126
18

I've spent too much time trying to get the finfo functions to work, properly. I finally just ended up creating my own function to match the file extension to any array of mime types. It's not a full-proof way of assuring that the files are truly what the extension denotes them to be, but that problem can be mitigated by how you process I/O of said files on your server(s).

function mime_type($file) {

    // there's a bug that doesn't properly detect
    // the mime type of css files
    // https://bugs.php.net/bug.php?id=53035
    // so the following is used, instead
    // src: http://www.freeformatter.com/mime-types-list.html#mime-types-list

    $mime_type = array(
        "3dml" => "text/vnd.in3d.3dml",
        "3g2" => "video/3gpp2",
        "3gp" => "video/3gpp",
        "7z" => "application/x-7z-compressed",
        "aab" => "application/x-authorware-bin",
        "aac" => "audio/x-aac",
        "aam" => "application/x-authorware-map",
        "aas" => "application/x-authorware-seg",
        "abw" => "application/x-abiword",
        "ac" => "application/pkix-attr-cert",
        "acc" => "application/vnd.americandynamics.acc",
        "ace" => "application/x-ace-compressed",
        "acu" => "application/vnd.acucobol",
        "adp" => "audio/adpcm",
        "aep" => "application/vnd.audiograph",
        "afp" => "application/vnd.ibm.modcap",
        "ahead" => "application/vnd.ahead.space",
        "ai" => "application/postscript",
        "aif" => "audio/x-aiff",
        "air" => "application/vnd.adobe.air-application-installer-package+zip",
        "ait" => "application/vnd.dvb.ait",
        "ami" => "application/vnd.amiga.ami",
        "apk" => "application/vnd.android.package-archive",
        "application" => "application/x-ms-application",
        // etc...
        // truncated due to Stack Overflow's character limit in posts
    );

    $extension = \strtolower(\pathinfo($file, \PATHINFO_EXTENSION));

    if (isset($mime_type[$extension])) {
        return $mime_type[$extension];
    } else {
        throw new \Exception("Unknown file type");
    }

}

Edit:

I'd like to address Davuz's comment (since it keeps getting up-voted) and remind everyone that I put in the pseudo disclaimer at the top that this isn't "full-proof." So, please keep that in mind when considering the approach I've offered in my answer.

Erutan409
  • 730
  • 10
  • 21
  • If you share a link to the final function I will give you a vote .) – dennis Jan 21 '15 at 12:57
  • 2
    Ask and you shall receive: https://gist.github.com/Erutan409/8e774dfb2b343fe78b14#file-mimetype-php – Erutan409 Jan 21 '15 at 13:24
  • 3
    what if I change file name "hamster.sh" to "hamster.jpg"? It's simply fail! – Davuz Jan 27 '15 at 07:30
  • If you had read my post/answer or looked at the gist source comments, you'll see the disclaimer regarding that, already. My suggestion would be to handle extension spoofing upon uploading. There's only so much you can do, anyway. You're the one that would be controlling files. – Erutan409 Jan 27 '15 at 11:42
  • 2
    you should use `$extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));` so it also detects mime-type for files with upper case extension – m132 Feb 21 '15 at 17:18
10

mime_content_type() is not deprecated and works fine.

Why is mime_content_type() deprecated in PHP?

http://php.net/manual/en/function.mime-content-type.php

As of PHP 5.3, it's even built-in.

Community
  • 1
  • 1
Anuga
  • 2,619
  • 1
  • 18
  • 27
  • 1
    Upvoted, but I'll also need to edit it, if you don't mind: saying it's "built-in" is misleading (at least it did mislead me ;) ): you still need the `fileinfo` extension for it to work! (The [page you referred to](http://php.net/manual/en/fileinfo.requirements.php) only said you can recompile the ext. without the `mime_magic` lib.) – Sz. Apr 05 '17 at 23:09
  • 1
    They've changed the text :) It's built-in, in Linux, but on Windows, you need to include the .dll in php.ini. – Anuga Apr 12 '17 at 11:55
4

$finfo = finfo_open(FILEINFO_MIME_TYPE); should do it.

Taken from the php.net docs. Your function is deprecated and probably already removed.

http://www.php.net/manual/en/function.finfo-file.php

Realitätsverlust
  • 3,941
  • 2
  • 22
  • 46
  • I got the Fatal error: Call to undefined function finfo_open() in. – Jitendra Yadav Apr 25 '14 at 08:07
  • 1
    @Jordan on other question said "PHP 5.3.0 and later have Fileinfo built in, but **on Windows you must enable it manually in your php.ini**. You can find further information in the documentation." – jave.web Jun 20 '14 at 17:46
  • Specifically, in your php.ini uncomment (remove `;`) this line: `;extension=php_fileinfo.dll` – jave.web Jan 22 '16 at 19:33
2

You should understand that file_get_contents will upload whole file to the memory, it is not good way to get only mime type. You don't need to use buffer method and file_get_contents function in this case.

To prevent any errors and warnings, better do like this.

$filename = 'path to your file';

if (class_exists('finfo')) {
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    if (is_object($finfo)) {
        echo $finfo->file($filename);
    }
} else {
    echo 'fileinfo did not installed';
}

Also you should know $finfo->file will throw PHP Warning if it fail.

If fileinfo is not installed properly, and you have a fresh version of PHP, you can get mime type from headers.

You can use cURL to get mime type from headers.

    $ch = curl_init();
    curl_setopt_array($ch, array(
            CURLOPT_HEADER => true,
            CURLOPT_NOBODY => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 1,
            CURLOPT_URL => $link)
    );

    $headers = curl_exec($ch);
    curl_close($ch);

    if (preg_match('/Content-Type:\s(.*)/i', $headers, $matches)) {
        echo trim($matches[1], "\t\n\r");
    }else {
        echo 'There is no content type in the headers!';
    }

Also you can use get_headers function, but it more slow than cURL request.

$url = 'http://www.example.com';

$headers = get_headers($url, 1);

echo $headers['Content-Type'];
madlopt
  • 415
  • 4
  • 7
  • *Content-Type returns a value depending only on the extension and not the real MIME TYPE. So, bad_file.exe renamed to good_file.doc will return application/msword - A file without extension returns a 404.* http://php.net/manual/en/function.get-headers.php#80460 – yckart Aug 08 '16 at 07:41
  • You can't trust everything in the internet. So, @yckart, you think will be better to overload your server and download all files and check it by content which can be also rewrited for preventing content type detection? **fileinfo**: _While this is not a bullet proof approach the heuristics used do a very good job._, - http://php.net/manual/en/intro.fileinfo.php – madlopt Aug 08 '16 at 11:38
2

Get the image size using:

$infFil=getimagesize($the_file_name);

and

echo $infFil["mime"]

The getimagesize returns an associative array which have a MIME key and obviously the image size too

I used it and it works

0

I use the MimeTypeTool from Bat (https://github.com/lingtalfi/Bat)

It uses fileinfo if available, and defaults back to an "extension => mime type" mapping otherwise.

ling
  • 9,545
  • 4
  • 52
  • 49
0

This is the best solution I found by combining two very good posts

// Thanks to http://php.net/manual/en/function.mime-content-type.php#87856

function getMimeContentType($filename, $ext)
{
    if(!function_exists('mime_content_type'))
    {
        if($mime_types = getMimeTypes())
        {
            if (array_key_exists($ext, $mime_types))
            {
                return $mime_types[$ext];
            }
            elseif (function_exists('finfo_open'))
            {
                $finfo  = finfo_open(FILEINFO_MIME);
                $mimetype = finfo_file($finfo, $filename);
                finfo_close($finfo);
                return $mimetype;
            }
        }
        return 'application/octet-stream';
    }
    return mime_content_type($filename);
}

// Thanks to http://php.net/manual/en/function.mime-content-type.php#107798

function getMimeTypes()
{
    $url = 'http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types';

    $mimes = array();
    foreach(@explode("\n",@file_get_contents($url)) as $x)
    {
        if(isset($x[0]) && $x[0]!=='#' && preg_match_all('#([^\s]+)#', $x, $out) && isset($out[1]) && ($c = count($out[1])) > 1)
        {
                for($i=1; $i < $c; $i++)
            {
                    $mimes[$out[1][$i]] = $out[1][0];
            }
        }
    }
    return (@sort($mimes)) ? $mimes : false;
}

Use it link this:

$filename = '/path/to/the/file.pdf';
$ext = strtolower(array_pop(explode('.',$filename)));
$content_type = getMimeContentType($filename, $ext);

Will continue to work even if the mime_content_type function is no longer supported in php.

Llewellyn
  • 388
  • 6
  • 19