Как мне найти MIME-тип файла с php?

Итак, у меня есть файл index.php, который должен обрабатывать множество разных типов файлов. как мне угадать тип файла на основе REQUEST_URI.

Если я запрашиваю http://site/image.jpg, и все запросы перенаправляются через index.php, который выглядит так

<?php
   include('/www/site'.$_SERVER['REQUEST_URI']);
?>

Как мне заставить это работать правильно?

Должен ли я тестировать на основе расширения запрошенного файла или есть способ получить тип файла?


person Issac Kelly    schedule 25.09.2008    source источник
comment
Можешь перефразировать свой вопрос? Я надеюсь, что вы действительно не запускаете такой код на своем веб-сайте.   -  person Till    schedule 25.09.2008
comment
Нет, конечно, это не так, как это на самом деле работает. Это был просто лучший способ донести мысль (так я думал).   -  person Issac Kelly    schedule 26.09.2008


Ответы (13)


Если вы уверены, что когда-либо работали только с изображениями, вы можете проверить getimagesize() exif_imagetype() PHP-функция, которая пытается вернуть MIME-тип изображения.

Если вы не возражаете против внешних зависимостей, вы также можете воспользоваться отличной библиотекой getID3, которая может определить MIME-тип множества различных типов файлов.

Наконец, вы можете проверить функцию mime_content_type(). - но он устарел для расширения Fileinfo PECL.

person leek    schedule 25.09.2008
comment
Вместо getimagesize() вызовите exif_imagetype(): us3.php. net/manual/en/function.exif-imagetype.php . Он предоставляет ту же информацию без потери производительности, связанной с выполнением других действий. - person Xiong Chiamiov; 17.01.2011
comment
Возвращаемое значение — это то же самое значение, которое getimagesize() возвращает в индексе 2, но exif_imagetype() намного быстрее. по приведенной выше ссылке, опубликованной @XiongChiamiov - person Tian Loon; 28.01.2014
comment
@leek: как получить тип пантомимы для любого контента .... stackoverflow.com/questions/21847663/ - person Hitesh; 21.02.2014

mime_content_type() устарел, поэтому вы не сможете рассчитывать на его работу в будущем. Существует расширение PECL «fileinfo», но я не слышал о нем хороших отзывов.

Если вы работаете на сервере * nix, вы можете сделать следующее, что отлично сработало для меня:

$file = escapeshellarg( $filename );
$mime = shell_exec("file -bi " . $file);
$filename should probably include the absolute path.
person Eric_WVGG    schedule 25.09.2008
comment
Команда file может быть отключена (на общих хостах) по соображениям безопасности. - person SAMPro; 09.12.2013
comment
Я не слышал об этом ничего хорошего. - Было бы неплохо, если бы мы могли прочитать то, что вы слышали ;) - person yckart; 08.07.2016
comment
Вы говорите, что mime_content_type устарела на основании чего? Не кажется устаревшим согласно php.net/manual/en /function.mime-content-type.php . - person Jānis Elmeris; 03.06.2020

function get_mime($file) {
  if (function_exists("finfo_file")) {
    $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala 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;
  }
}

Для меня ничего из этого не работает - mime_content_type устарело, finfo не установлено, а shell_exec не разрешено.

person Ale    schedule 30.08.2012

Мне на самом деле надоело отсутствие стандартных методов анализа MIME в PHP. Установите fileinfo... Используйте устаревшие функции... О, это работает, но только для изображений! Мне это надоело, поэтому я провел небольшое исследование и нашел спецификацию WHATWG Mimesniffing — я верю в это. хотя это все еще черновая спецификация.

В любом случае, используя эту спецификацию, я смог реализовать мимесниффер на PHP. Производительность не проблема. Фактически, на моей скромной машине я смог открыть и пронюхать тысячи файлов до истечения времени ожидания PHP.

Вот класс MimeReader.

require_once("MimeReader.php");

$mime = new MimeReader(<YOUR FILE PATH>);
$mime_type_string = $mime->getType();     // "image/jpeg" etc.
person Shane    schedule 01.08.2013
comment
Звучит здорово! Сейчас Living Standard — Last Updated 11 June 2013, так что не черновик. Удалось ли вам загрузить/поделиться где-нибудь своим PHP-кодом, используя это? - person trejder; 10.09.2013
comment
Привет Трейдер. Спасибо за это обновление, и извините за поздний ответ. Вы можете найти все мои проекты, размещенные на моем мини-сайте (знаю, его немного). Я, вероятно, выложу его на github, если он станет популярным. Все в проектах. Он выпущен в общественное достояние, поэтому не стесняйтесь подчищать код (это необходимо!) или иным образом модифицировать по своему усмотрению. shane.social-library.org - person Shane; 20.09.2013
comment
Спасибо! Я обязательно посмотрю на это! :] - person trejder; 20.09.2013
comment
Привет, Сайед Кариб, спасибо, что сообщили мне. Я обновил ссылку на github, как вы и предложили. - person Shane; 04.08.2015
comment
Этот класс не имеет типа CSV. - person Jarosław Osmólski; 24.09.2015
comment
Правильно - это потому, что файлы CSV представляют собой обычный текст, это работает исключительно с магическим числом, поэтому, что касается класса, это обычный текст. Вы должны иметь возможность проверить эти простые текстовые файлы, если хотите их отличить, или, пожалуйста, не стесняйтесь сделать форк. Спасибо - person Shane; 29.09.2015
comment
@Шейн, это не работает... Я получаю сообщение об ошибке: Fatal error: Call to undefined method MimeReader::get_type() in /home/***/public_html/editor.php on line 189 - person Yaakov Ainspan; 08.09.2016
comment
Привет Tricks for the Web, сколько лет версии, которую вы используете? Если у вас есть недавняя копия, API немного изменился со змеиным_кейсом на верблюжий, поэтому подходящей функцией теперь является getType. Извините за путаницу! - person Shane; 09.09.2016

Если вы работаете только с изображениями и вам нужен MIME-тип (например, для заголовков), то это самый быстрый и прямой ответ:

$file = 'path/to/image.jpg';
$image_mime = image_type_to_mime_type(exif_imagetype($file));

Он выведет истинный тип mime изображения, даже если вы переименуете файл изображения.

person Andrew    schedule 06.03.2013

Согласно руководству по php, функция finfo-file лучший способ сделать это. Однако вам потребуется установить расширение PECL FileInfo.

Если расширение не подходит, вы можете использовать устаревшую функцию mime_content_type.

person Devon    schedule 25.09.2008
comment
Также. Расширение Fileinfo включено по умолчанию, начиная с PHP 5.3. - person Stann; 23.05.2011
comment
@Стэнн Нет, это не так! PHP Version 5.4.7 + Fatal error: Call to undefined function finfo_open() in C:\XAMPP\htdocs\.... - person trejder; 10.09.2013

mime_content_type() кажется подходящим вариантом, несмотря на приведенные выше комментарии о том, что он устарел. Это не так — или, по крайней мере, это воплощение mime_content_type() не устарело, согласно http://php.net/manual/en/function.mime-content-type.php. Это часть расширения FileInfo, но в документации по PHP теперь говорится, что оно включено по умолчанию, начиная с PHP 5.3.0.

person David    schedule 31.01.2016

Вы можете использовать finfo для этого, начиная с PHP 5.3:

<?php
$info = new finfo(FILEINFO_MIME_TYPE);
echo $info->file('myImage.jpg');
// prints "image/jpeg"

Флаг FILEINFO_MIME_TYPE является необязательным; без него вы получите более подробную строку для некоторых файлов; (очевидно, некоторые типы изображений будут возвращать информацию о размере и глубине цвета). Использование флага FILEINFO_MIME возвращает MIME-тип и кодировку, если они доступны (например, изображение/png; charset=binary или text/x-php; charset=us-ascii). Дополнительную информацию см. на этом сайте.

person jhaagsma    schedule 12.10.2016

Я не использовал его, но есть расширение PECL для получения MIME-типа файла. Официальная документация для него находится в руководстве.

В зависимости от ваших целей расширение файла может быть приемлемым, но оно не очень надежно, поскольку его так легко изменить.

person enobrev    schedule 25.09.2008

я получил очень хорошие результаты, используя пользовательскую функцию из http://php.net/manual/de/function.mime-content-type.php @''Джон Дот Ховард, prismmg dot com, 26 октября 2009 г., 03:43''

function get_mime_type($filename, $mimePath = '../etc') { ...

который не использует finfo, exec или устаревшую функцию

хорошо работает и с удаленными ресурсами!

person vizzy    schedule 12.09.2012
comment
Эта функция была устарела задолго до того, как вы написали этот ответ, поэтому предлагать это решение бессмысленно. - person trejder; 10.09.2013

если вы имеете дело только с изображениями, вы можете использовать функцию [getimagesize()][1], которая содержит все виды информации об изображении, включая тип.

Более общий подход заключается в использовании расширения FileInfo из PECL. Документацию PHP для этого расширения можно найти по адресу: http://us.php.net/manual/en/ref.fileinfo.php

У некоторых людей есть серьезные жалобы на это расширение... поэтому, если вы столкнетесь с серьезными проблемами или не сможете установить расширение по какой-либо причине, вы можете проверить устаревшую функцию mime_content_type()

person phatduckk    schedule 25.09.2008

Если вы используете Linux и имеете расширение, вы можете просто прочитать MIME-тип из /etc/mime.types, создав хэш-массив. Затем вы можете сохранить это в памяти и просто вызвать MIME по ключу массива :)

/**
 * 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;
}
person Klemen Tusar    schedule 24.08.2016

С помощью этого можно получить mime любого файла на вашем сервере.

<?php
function get_mime($file_path){
  $finfo = new finfo(FILEINFO_MIME_TYPE);
  $type  = $finfo->file(file_path);
}

$mime = get_mime('path/to/file.ext');
person Joshua    schedule 28.11.2017