- Getting the Mimetype of an Image with PHP
- image_type_to_mime_type
- Список параметров
- Возвращаемые значения
- Примеры
- mime_content_type
- Parameters
- Return Values
- Errors/Exceptions
- Examples
- See Also
- User Contributed Notes 21 notes
- Работа с MIME-типами в PHP
- Как узнать MIME-тип загруженного файла
- Результат:
- Отправка файлов из PHP
Getting the Mimetype of an Image with PHP
This is awesome. I was so fed up with trying to find a fail-proof, cross-platform way to find the mime type of an image using PHP that I wrote a quick function that utilizes the same technology as the exif_imagetype, getimagesize, and finfo functions do.
Basically, the method is the exact same as that used by all magic file type enumerators. Just open the file/stream in read-binary mode and grab the file header (the first few bytes). I opted to keep it simple and super-fast and just used == , otherwise you can use preg_match with the /s .
This is also the same method used by imagemagick, Apache, really everything that does it low-level.
Use the return as the arg to image_type_to_mime_type to get the mime string.
// oh no he didnt
function askapache_get_image_filetype ( $file ) if ( ! is_file ( $file ) || ! is_readable ( $file ) )
return false ;
if ( false === $fp = fopen ( $file , ‘rb’ ) )
return false ;
if ( false === $file_size = filesize ( $file ) )
return false ;
if ( $file_size < 13 )
return false ;
if ( false === $line = fread ( $fp , 12 ) )
return false ;
$l2 = substr ( $line , 0 , 2 );
$l3 = substr ( $line , 0 , 3 );
$l4 = substr ( $line , 0 , 4 );
$l7 = substr ( $line , 0 , 7 );
$l8 = substr ( $line , 0 , 8 );
$image_type_num = IMAGETYPE_UNKNOWN ;
if ( $l2 == ‘BM’ ) $image_type_num = IMAGETYPE_BMP ;
> elseif ( $l3 == «\377\330\377» ) $image_type_num = IMAGETYPE_JPEG ;
> elseif ( $l3 == ‘GIF’ ) $image_type_num = IMAGETYPE_GIF ;
> elseif ( $l4 == «\000\000\001\000» ) $image_type_num = IMAGETYPE_ICO ;
> elseif ( $l4 == «II\052\000» ) $image_type_num = IMAGETYPE_TIFF_II ;
> elseif ( $l4 == «MM\000\052» ) $image_type_num = IMAGETYPE_TIFF_MM ;
> elseif ( $l7 == ‘#define’ ) $image_type_num = IMAGETYPE_XBM ;
> elseif ( $l8 == «\211\120\116\107\015\012\032\012» ) $image_type_num = IMAGETYPE_PNG ;
>
This is well 1000x more efficient than a exec like system(‘file -i -b —mime-type $f’); could ever be.. (and you should disabled exec functions like that anyway).
And from the source php-5.4.13
// file type markers
PHPAPI const char php_sig_gif [ 3 ] = < 'G' , 'I' , 'F' >;
PHPAPI const char php_sig_psd [ 4 ] = < '8' , 'B' , 'P' , 'S' >;
PHPAPI const char php_sig_bmp [ 2 ] = < 'B' , 'M' >;
PHPAPI const char php_sig_swf [ 3 ] = < 'F' , 'W' , 'S' >;
PHPAPI const char php_sig_swc [ 3 ] = < 'C' , 'W' , 'S' >;
PHPAPI const char php_sig_jpg [ 3 ] = < 0xff , 0xd8 , 0xff >;
PHPAPI const char php_sig_png [ 8 ] = < 0x89 , 0x50 , 0x4e , 0x47 , 0x0d , 0x0a , 0x1a , 0x0a >;
PHPAPI const char php_sig_tif_ii [ 4 ] = < 'I' , 'I' , 0x2A , 0x00 >;
PHPAPI const char php_sig_tif_mm [ 4 ] = < 'M' , 'M' , 0x00 , 0x2A >;
PHPAPI const char php_sig_jpc [ 3 ] = < 0xff , 0x4f , 0xff >;
PHPAPI const char php_sig_jp2 [ 12 ] = < 0x00 , 0x00 , 0x00 , 0x0c , 0x6a , 0x50 , 0x20 , 0x20 , 0x0d , 0x0a , 0x87 , 0x0a >;
PHPAPI const char php_sig_iff [ 4 ] = < 'F' , 'O' , 'R' , 'M' >;
PHPAPI const char php_sig_ico [ 4 ] = < 0x00 , 0x00 , 0x01 , 0x00 >;
1 IMAGETYPE_GIF
2 IMAGETYPE_JPEG
3 IMAGETYPE_PNG
4 IMAGETYPE_SWF
5 IMAGETYPE_PSD
6 IMAGETYPE_BMP
7 IMAGETYPE_TIFF_II ( intel byte order )
8 IMAGETYPE_TIFF_MM ( motorola byte order )
9 IMAGETYPE_JPC
10 IMAGETYPE_JP2
11 IMAGETYPE_JPX
12 IMAGETYPE_JB2
13 IMAGETYPE_SWC
14 IMAGETYPE_IFF
15 IMAGETYPE_WBMP
16 IMAGETYPE_XBM
17 IMAGETYPE_ICO
?>
static const MagicMapInfo MagicMap[] = < < "8BIMWTEXT", 0, "8\000B\000I\000M\000#" >, < "8BIMTEXT", 0, "8BIM#" >, < "8BIM", 0, "8BIM" >, < "BMP", 0, "BA" >, < "BMP", 0, "BM" >, < "BMP", 0, "CI" >, < "BMP", 0, "CP" >, < "BMP", 0, "IC" >, < "PICT", 0, "PICT" >, < "BMP", 0, "PI" >, < "CALS", 21, "version: MIL-STD-1840" >, < "CALS", 0, "srcdocid:" >, < "CALS", 9, "srcdocid:" >, < "CALS", 8, "rorient:" >, < "CGM", 0, "BEGMF" >, < "CIN", 0, "\200\052\137\327" >, < "CRW", 0, "II\x1a\x00\x00\x00HEAPCCDR" >, < "DCM", 128, "DICM" >, < "DCX", 0, "\261\150\336\72" >, < "DIB", 0, "\050\000" >, < "DDS", 0, "DDS " >, < "DJVU", 0, "AT&TFORM" >, < "DOT", 0, "digraph" >, < "DPX", 0, "SDPX" >, < "DPX", 0, "XPDS" >, < "EMF", 40, "\040\105\115\106\000\000\001\000" >, < "EPT", 0, "\305\320\323\306" >, < "EXR", 0, "\166\057\061\001" >, < "FAX", 0, "DFAX" >, < "FIG", 0, "#FIG" >, < "FITS", 0, "IT0" >, < "FITS", 0, "SIMPLE" >, < "FPX", 0, "\320\317\021\340" >, < "GIF", 0, "GIF8" >, < "GPLT", 0, "#!/usr/local/bin/gnuplot" >, < "HDF", 1, "HDF" >, < "HDR", 0, "#?RADIANCE" >, < "HDR", 0, "#?RGBE" >, < "HPGL", 0, "IN;" >, < "HTML", 1, "HTML" >, < "HTML", 1, "html" >, < "ILBM", 8, "ILBM" >, < "IPTCWTEXT", 0, "\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000" >, < "IPTCTEXT", 0, "2#0=\042\042" >, < "IPTC", 0, "\034\002" >, < "JNG", 0, "\213JNG\r\n\032\n" >, < "JPEG", 0, "\377\330\377" >, < "JPC", 0, "\377\117" >, < "JP2", 4, "\152\120\040\040\015" >, < "MAT", 0, "MATLAB 5.0 MAT-file," >, < "MIFF", 0, "Id=ImageMagick" >, < "MIFF", 0, "id=ImageMagick" >, < "MNG", 0, "\212MNG\r\n\032\n" >, < "MPC", 0, "id=MagickCache" >, < "MPEG", 0, "\000\000\001\263" >, < "MRW", 0, "\x00MRM" >, < "MVG", 0, "push graphic-context" >, < "ORF", 0, "IIRO\x08\x00\x00\x00" >, < "PCD", 2048, "PCD_" >, < "PCL", 0, "\033E\033" >, < "PCX", 0, "\012\002" >, < "PCX", 0, "\012\005" >, < "PDB", 60, "vIMGView" >, < "PDF", 0, "%PDF-" >, < "PES", 0, "#PES" >, < "PFA", 0, "%!PS-AdobeFont-1.0" >, < "PFB", 6, "%!PS-AdobeFont-1.0" >, < "PGX", 0, "\050\107\020\115\046" >, < "PICT", 522, "\000\021\002\377\014\000" >, < "PNG", 0, "\211PNG\r\n\032\n" >, < "PBM", 0, "P1" >, < "PGM", 0, "P2" >, < "PPM", 0, "P3" >, < "PBM", 0, "P4" >, < "PGM", 0, "P5" >, < "PPM", 0, "P6" >, < "PAM", 0, "P7" >, < "PFM", 0, "PF" >, < "PFM", 0, "Pf" >, < "PS", 0, "%!" >, < "PS", 0, "\004%!" >, < "PS", 0, "\305\320\323\306" >, < "PSB", 0, "8BPB" >, < "PSD", 0, "8BPS" >, < "PWP", 0, "SFW95" >, < "RAF", 0, "FUJIFILMCCD-RAW " >, < "RLE", 0, "\122\314" >, < "SCT", 0, "CT" >, < "SFW", 0, "SFW94" >, < "SGI", 0, "\001\332" >, < "SUN", 0, "\131\246\152\225" >, < "SVG", 1, "?XML" >, < "SVG", 1, "?xml" >, < "TIFF", 0, "\115\115\000\052" >, < "TIFF", 0, "\111\111\052\000" >, < "TIFF64", 0, "\115\115\000\053\000\010\000\000" >, < "TIFF64", 0, "\111\111\053\000\010\000\000\000" >, < "TTF", 0, "\000\001\000\000\000" >, < "TXT", 0, "# ImageMagick pixel enumeration:" >, < "VICAR", 0, "LBLSIZE" >, < "VICAR", 0, "NJPL1I" >, < "VIFF", 0, "\253\001" >, < "WEBP", 8, "WEBP" >, < "WMF", 0, "\327\315\306\232" >, < "WMF", 0, "\001\000\011\000" >, < "WPG", 0, "\377WPC" >, < "XBM", 0, "#define" >, < "XCF", 0, "gimp xcf" >, < "XEF", 0, "FOVb" >, < "XPM", 1, "* XPM *" >, < "XWD", 4, "\007\000\000" >, < "XWD", 5, "\000\000\007" >>;
image_type_to_mime_type
Функция image_type_to_mime_type() определяет Mime-тип для константы IMAGETYPE.
Список параметров
Одна из констант IMAGETYPE_XXX .
Возвращаемые значения
Возвращаемые значения приведены ниже
image_type | Возвращаемое значение |
---|---|
IMAGETYPE_GIF | image/gif |
IMAGETYPE_JPEG | image/jpeg |
IMAGETYPE_PNG | image/png |
IMAGETYPE_SWF | application/x-shockwave-flash |
IMAGETYPE_PSD | image/psd |
IMAGETYPE_BMP | image/bmp |
IMAGETYPE_TIFF_II (порядок байт intel) | image/tiff |
IMAGETYPE_TIFF_MM (порядок байт motorola) | image/tiff |
IMAGETYPE_JPC | application/octet-stream |
IMAGETYPE_JP2 | image/jp2 |
IMAGETYPE_JPX | application/octet-stream |
IMAGETYPE_JB2 | application/octet-stream |
IMAGETYPE_SWC | application/x-shockwave-flash |
IMAGETYPE_IFF | image/iff |
IMAGETYPE_WBMP | image/vnd.wap.wbmp |
IMAGETYPE_XBM | image/xbm |
IMAGETYPE_ICO | image/vnd.microsoft.icon |
IMAGETYPE_WEBP | image/webp |
Примеры
Пример #1 Пример использования image_type_to_mime_type()
mime_content_type
Returns the MIME content type for a file as determined by using information from the magic.mime file.
Parameters
Return Values
Returns the content type in MIME format, like text/plain or application/octet-stream , or false on failure.
Errors/Exceptions
Upon failure, an E_WARNING is emitted.
Examples
Example #1 mime_content_type() Example
The above example will output:
See Also
User Contributed Notes 21 notes
Fast generation of uptodate mime types:
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’,
.
There is a composer package that will do this:
https://github.com/ralouphie/mimey
$mimes = new \ Mimey \ MimeTypes ;
// Convert extension to MIME type:
$mimes -> getMimeType ( ‘json’ ); // application/json
// Convert MIME type to extension:
$mimes -> getExtension ( ‘application/json’ ); // json
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).
For me mime_content_type didn’t work in Linux before I added
to php.ini (remember to find the correct path to mime.magic)
using
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 ($file);
>
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:
echo system ( «file -bi »» );
?>
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:
echo system ( «file -b »» ); // 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.
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.
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.
>> 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:
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 );
>
?>
Работа с MIME-типами в PHP
«Internet Media Types» или «Медиа типы» — является стандартом RFC 6838, который описывает формат файла. Причем браузеры используют MIME-типы в качестве основного критерия, не воспринимая расширения файлов.
MIME-тип состоит из типа и подтипа — двух значений разделённых « / », без использования пробелов и в нижнем регистре, например HTML страница:
Полный список MIME типов можно посмотреть тут.
К медиа типу может быть добавлен параметр для указания дополнительных деталей (например кодировка):
Как узнать MIME-тип загруженного файла
При загрузке файла через форму, MIME-тип файла доступен в массиве $_FILES , например:
Для определения MIME уже загруженного файла существует PHP-функция mime_content_type().
echo mime_content_type(__DIR__ . '/image.png'); // image/png echo mime_content_type(__DIR__ . '/text.txt'); // text/plain
При работе с изображениями, MIME-тип можно получить с помощью функции getimagesize():
$filename = __DIR__ . '/image.png'; $info = getimagesize($filename); print_r($info);
Результат:
Array ( [0] => 221 [1] => 96 [2] => 3 [3] => width="221" height="96" [bits] => 8 [mime] => image/png )
Важно помнить что при проверке файлов нельзя полагаться только на проверку MIME, т.к. его значение может быть скомпрометировано. Поэтому нужно проводить более детальную проверку (например по размеру изображения или его пересохранить в предполагаемом формате).
Отправка файлов из PHP
В PHP-скриптах, перед отправкой файлов клиенту, необходимо отправлять заголовок Content-Type , например файл XML:
$content = '. '; header("Content-Type: text/xml; charset=utf-8"); echo $content; exit();
$file = ROOT_DIR . '/market.zip'; header('Content-type: application/zip'); header('Content-Transfer-Encoding: Binary'); header('Content-length: ' . filesize($file)); header('Content-disposition: attachment; filename="' . basename($file) . '"'); readfile($file); exit();
Вывод изображения в зависимости от расширения файла:
$filename = __DIR__ . '/image.png'; $ext = mb_strtolower(mb_substr(mb_strrchr($filename, '.'), 1)); switch ($ext) < case 'png': header('Content-type: image/png'); break; case 'jpg': case 'jpeg': header('Content-type: image/jpeg'); break; case 'gif': header('Content-type: image/gif'); break; case 'wepb': header('Content-type: image/webp'); break; >readfile($filename); exit();