mime_content_type()
(PHP 4 >= 4.3.0, PHP 5, PHP 7)
检测文件的 MIME 类型
说明
mime_content_type(string $filename): string
返回通过使用magic.mime检测到的文件 MIME 类型。
参数
- $filename
要检测的文件名。
返回值
返回文件的 MIME 内容类型,例如text/plain或application/octet-stream。或者在失败时返回FALSE
。
错误/异常
失败时抛出E_WARNING
警告。
范例
mime_content_type()示例
<?php echo mime_content_type('php.gif') . "\n"; echo mime_content_type('test.php'); ?>
以上例程会输出:
image/gif text/plain
参见
finfo_file()
别名 finfo_file()finfo_buffer()
别名 finfo_buffer()
Fast generation of uptodate mime types: <?php define('APACHE_MIME_TYPES_URL','http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); function generateUpToDateMimeArray($url){ $s=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++) $s[]=' \''.$out[1][$i].'\' => \''.$out[1][0].'\''; return @sort($s)?'$mime_types = array(<br />'.implode($s,',<br />').'<br />);':false; } echo generateUpToDateMimeArray(APACHE_MIME_TYPES_URL); ?> Output: $mime_types = array( '123' => 'application/vnd.lotus-1-2-3', '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', ... Enjoy.
Completing <some dude AT somewhere DOT com> comment: 0 string < ? php application/x-httpd-php and string detection on text files may fail if you check a file encoded with signed UTF-8. The UTF-8 signature is a two bytes code (0xFF 0xFE) that prepends the file in order to force UTF-8 recognition (you may check it on an hexadecimal editor).
There is a composer package that will do this: https://github.com/ralouphie/mimey <?php $mimes = new \Mimey\MimeTypes; // Convert extension to MIME type: $mimes->getMimeType('json'); // application/json // Convert MIME type to extension: $mimes->getExtension('application/json'); // json
Regarding serkanyersen's example : It is advisable to change the regular expression to something more precise like preg_match("|\.([a-z0-9]{2,4})$|i", $filename, $m); This makes sure that only the last few characters are taken. The original expression would not work if the filename is a relative path.
I see a lot of comments suggesting doing file extension sniffing (i.e. assuming .jpg files are JPEG images) when proper file-type sniffing functions are unavailable. I want to point out that there is a much more accurate way. If neither mime_content_type() nor Fileinfo is available to you and you are running *any* UNIX variant since the 70s, including Mac OS, OS X, Linux, etc. (and most web hosting is), just make a system call to 'file(1)'. Doing something like this: <?php echo system("file -bi '<file path>'"); ?> will output something like "text/html; charset=us-ascii". Some systems won't add the charset bit, but strip it off just in case. The '-bi' bit is important. However, you can use a command like this: <?php echo system("file -b '<file path>'"); // without the 'i' after '-b' ?> to output a human-readable string, like "HTML document text", which can sometimes be useful. The only drawback is that your scripts will not work on Windows, but is this such a problem? Just about all web hosts use a UNIX. It is a far better way than just examining the file extension.
using <?php function detectFileMimeType($filename='') { $filename = escapeshellcmd($filename); $command = "file -b --mime-type -m /usr/share/misc/magic {$filename}"; $mimeType = shell_exec($command); return trim($mimeType); } ?> should work on most shared linux hosts without errors. It should also work on Windows hosts with msysgit installed.
Lukas V is IMO missing some point. The MIME type of a file may not be corresponding to the file suffix. Imagine someone would obfuscate some PHP code in a .gif file, the file suffix would be 'GIF' but the MIME would be text/plain or even text/html. Another example is files fetched via a distant server (wget / fopen / file / fsockopen...). The server can issue an error, i.e. 404 Not Found, wich again is text/html, whatever you save the file to (download_archive.rar). His provided function should begin by the test of the function existancy like : function MIMEalternative($file) { if(function_exists('mime_content_type')) return mime_content_type($file); else return <lukas_v.MIMEfunction>($file); }
if you use a transparent 'spacer' GIF i've found it needs to be a around 25x25 for it to register as 'image/gif'. otherwise it's read in as 'text/plain'.
<?php if(!function_exists('mime_content_type')) { function mime_content_type($filename) { $mime_types = array( 'txt' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', 'php' => 'text/html', 'css' => 'text/css', 'js' => 'application/javascript', 'json' => 'application/json', 'xml' => 'application/xml', 'swf' => 'application/x-shockwave-flash', 'flv' => 'video/x-flv', // images 'png' => 'image/png', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'bmp' => 'image/bmp', 'ico' => 'image/vnd.microsoft.icon', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', // archives 'zip' => 'application/zip', 'rar' => 'application/x-rar-compressed', 'exe' => 'application/x-msdownload', 'msi' => 'application/x-msdownload', 'cab' => 'application/vnd.ms-cab-compressed', // audio/video 'mp3' => 'audio/mpeg', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', // adobe 'pdf' => 'application/pdf', 'psd' => 'image/vnd.adobe.photoshop', 'ai' => 'application/postscript', 'eps' => 'application/postscript', 'ps' => 'application/postscript', // ms office 'doc' => 'application/msword', 'rtf' => 'application/rtf', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', // open office 'odt' => 'application/vnd.oasis.opendocument.text', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', ); $ext = strtolower(array_pop(explode('.',$filename))); 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; } else { return 'application/octet-stream'; } } } ?>
For me mime_content_type didn't work in Linux before I added mime_magic.magicfile = "/usr/share/magic.mime" to php.ini (remember to find the correct path to mime.magic)
The correct little correction: exec will return the mime with a newline at the end, the trim() should be called with the result of exec, not the other way around. <?php if ( ! function_exists ( 'mime_content_type ' ) ) { function mime_content_type ( $f ) { return trim ( exec ('file -bi ' . escapeshellarg ( $f ) ) ) ; } } ?>
Here's a simple function to return MIME types, based on the Apache mime.types file. [The one in my previous submission, which has since been replaced by this one] only works properly if mime.types is formatted as Windows text. The updated version below corrects this problem. Thanks to Mike for pointing this out. <?php function get_mime_type($filename, $mimePath = '../etc') { $fileext = substr(strrchr($filename, '.'), 1); if (empty($fileext)) return (false); $regex = "/^([\w\+\-\.\/]+)\s+(\w+\s)*($fileext\s)/i"; $lines = file("$mimePath/mime.types"); foreach($lines as $line) { if (substr($line, 0, 1) == '#') continue; // skip comments $line = rtrim($line) . " "; if (!preg_match($regex, $line, $matches)) continue; // no match to the extension return ($matches[1]); } return (false); // no match at all } ?> Notes: [1] Requires mime.types file distributed with Apache (normally found at ServerRoot/conf/mime.types). If you are using shared hosting, download the file with the Apache distro and then upload it to a directory on your web server that php has access to. [2] First param is the filename (required). Second parameter is path to mime.types file (optional; defaults to home/etc/). [3] Based on MIME types registered with IANA (http://www.iana.org/assignments/media-types/index.html). Recognizes 630 extensions associated with 498 MIME types. [4] Asserts MIME type based on filename extension. Does not examine the actual file; the file does not even have to exist. [5] Examples of use: >> echo get_mime_type('myFile.xml'); >> application/xml >> echo get_mime_type('myPath/myFile.js'); >> application/javascript >> echo get_mime_type('myPresentation.ppt'); >> application/vnd.ms-powerpoint >> echo get_mime_type('http://mySite.com/myPage.php); >> application/x-httpd-php >> echo get_mime_type('myPicture.jpg'); >> image/jpeg >> echo get_mime_type('myMusic.mp3'); >> audio/mpeg and so on... To create an associative array containing MIME types, use: <?php function get_mime_array($mimePath = '../etc') { $regex = "/([\w\+\-\.\/]+)\t+([\w\s]+)/i"; $lines = file("$mimePath/mime.types", FILE_IGNORE_NEW_LINES); foreach($lines as $line) { if (substr($line, 0, 1) == '#') continue; // skip comments if (!preg_match($regex, $line, $matches)) continue; // skip mime types w/o any extensions $mime = $matches[1]; $extensions = explode(" ", $matches[2]); foreach($extensions as $ext) $mimeArray[trim($ext)] = $mime; } return ($mimeArray); } ?>
I also had issues with this function. The issue was that it would almost always return "text/plain". echo ini_get('mime_magic.magicfile'); // returns /etc/httpd/conf/magic I found that I needed the OS' magic.mime file instead. You can either copy it to the existing location, or update your php.ini, you cannot use ini_set(). [root@blade conf]# mv magic magic.old [root@blade conf]# cp /usr/share/magic.mime magic [root@blade conf]# apachectl graceful Note: you will see that I have gracefully restarted apache to ensure it has taken affect.
<?PHP function qmimetype($file) { $ext=array_pop(explode('.',$file)); foreach(file('/usr/local/etc/apache22/mime.types') as $line) if(preg_match('/^([^#]\S+)\s+.*'.$ext.'.*$/',$line,$m)) return $m[1]; return 'application/octet-stream'; } ?> Not perfect, but works good enough for me ;)
I added these two lines to my magic.mime file: 0 string \<?php application/x-httpd-php 0 string \<?xml text/xml The first one may not work if "<?php" is not at the very beginning of your file, e.g., if some HTML preceeds the first bit of PHP code. The second one should work because "<?xml" *should* be the first thing in every XML file.
The function mime_content_type only worked for me on Microsoft Windows after I added the directive "mime_magic.debug" to my php.ini with the value of "On". The default value appears to be "Off". Exampe: [mime_magic] mime_magic.debug = On mime_magic.magicfile = "c:\php\extras\magic.mime"
// Here is a working version of a function that fetches the meme types from apache's built in mime list and creates an array of which the keys are the file extensions: function generateUpToDateMimeArray($url){ $return = array(); $mimes = file_get_contents('http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); // make sure that allow_url_fopen is enabled! preg_match_all('#^([^\s]{2,}?)\s+(.+?)$#ism', $mimes, $matches, PREG_SET_ORDER); foreach ($matches as $match){ $exts = split(" ", $match[2]); foreach ($exts as $ext){ $return[$ext]=$match[1]; } } return $return; } // usage: $typeMime = generateUpToDateMimeArray(); echo $typeMime['gif'];
Slight improvement over Josh Sean's code: this makes a usable and formatted php file containing the latest mime associations ( strictly using the file extension) in an array or if the file_get_contents fails ( say you are offline ) leaves the original file alone. I made it a bit "dummer" for readability purposes, don't judge me just improve it on your own. <?php define('APACHE_MIME_TYPES_URL','http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); function generateUpToDateMimeArray($url){ $s=array(); $result = @file_get_contents($url); if ($result == FALSE ) { $returned = "ERROR"; } else { foreach(@explode("\n",$result)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++) $s[]=' \''.$out[1][$i].'\' => \''.$out[1][0].'\''; } $returned = @sort($s)?'<?php' . "\n" . '$mime_types = array(' . "\n" . implode($s,",\n") . "\n);\n" . '?>':false; } return $returned; } $file_name = 'mime-array.php'; $data = generateUpToDateMimeArray(APACHE_MIME_TYPES_URL); if ($data != "ERROR") { $file = fopen($file_name, 'wb') or die("cannot open $file_name\n"); fwrite($file, $data ) or die("cannot write data\n"); fclose($file); echo "updated"; } else { echo "faliure"; } ?> All you need to do is run it once and in your code you can simply add these two lines: <?php include 'mime-array.php'; global $mime_types; ?> enjoy
additional to svogal's video files: 'mp4' => 'video/mp4', what also works: 'mp4' => 'audio/mp4',
Since I enabled the mime_magic extension on my IIS, I also got the error message "invalid magic file, disabled" in my phpinfo. After I add these lines to my php.ini, the message disappeared and it works great! mime_magic.debug = Off mime_magic.magicfile ="D:\PHP5\extras\magic.mime" mime_magic.debug is by default off but without this line it fails. I'm using PHP 5.2.5.