Как определить MIME-тип файлы средствами PHP? Php как по содержанию определить тип файла

  • 03.11.2019

Последняя линия близка. Вы можете использовать: if (mime_content_type($_FILES["fupload"]["tmp_name"]) == "image/gif"){...

В случае, когда я сейчас работаю, мой $_FILES..["type"] сообщает себя как «text / csv», в то время как mime_content_type() и finfo() (предлагаемые другими) сообщают «text / plain». , Как отмечает @deceze, $_FILES..["type"] полезно только знать, какой тип клиент считает файлом.

ПРЕДУПРЕЖДЕНИЕ : следующий ответ фактически не проверяет тип файла. Он проверяет только имя. Он не подходит для реальных целей безопасности.

EDIT: не используйте этот метод, поскольку он не выполняет проверку безопасности. Я оставляю этот ответ здесь, чтобы никто не делал такую ​​же ошибку, как я, пытаясь это сделать.

Я попробовал следующее, и это сработало для меня:

$allowed = array("gif","png" ,"jpg", "pdf"); $filename = $_FILES["input_tag_name"]["name"]; $ext = pathinfo($filename, PATHINFO_EXTENSION); if(!in_array($ext,$allowed)) { echo "error"; }

В PHP 5.5 я использую эту функцию для получения типа файла и проверяю, есть ли изображение:

Function getFileType($file) { return image_type_to_mime_type(exif_imagetype($file)); } // Get file type $file_type = getFileType("path/to/images/test.png"); echo $file_type; // Prints image/png // 1. All images have mime type starting with "image" // 2. No other non-image mime types contain string "image" in it

Тогда вы могли бы сделать:

If (strpos($filetype, "image") !== false) { // This is an image }

Это простой сценарий с одной строкой, который я часто использую.

$image = "/var/www/Core/temp/image.jpg"; $isImage = explode("/", mime_content_type()) == "image";

В основном я использую mime_content_type (), чтобы получить что-то вроде «image / jpg», а затем взломать его «/» и проверить на первый элемент массива, чтобы увидеть, говорит ли он «образ».

Надеюсь это работает!

Конечно, вы можете проверить, есть ли это изображение с exif, но лучший способ, я думаю, это сделать с finfo следующим образом:

$allowed_types = array ("application/pdf", "image/jpeg", "image/png"); $fileInfo = finfo_open(FILEINFO_MIME_TYPE); $detected_type = finfo_file($fileInfo, $_FILES["datei"]["tmp_name"]); if (!in_array($detected_type, $allowed_types)) { die ("Please upload a pdf or an image "); } finfo_close($fileInfo);

В дополнение к @deceze вы также можете finfo() проверить MIME-тип файлов без изображения:

$finfo = new finfo(); $fileMimeType = $finfo->file($path . $filename, FILEINFO_MIME_TYPE);

Function assignFilePreviews() { $("input").change(function() { var prvCnt = $(this).attr("data-preview-container"); if (prvCnt) { if (this.files && this.files) { var reader = new FileReader(); reader.onload = function(e) { var img = $(""); img.attr("src", e.target.result); img.error(function() { $(prvCnt).html(""); }); $(prvCnt).html(""); img.appendTo(prvCnt); } reader.readAsDataURL(this.files); } } }); } $(document).ready(function() { assignFilePreviews(); });

Это также обрабатывает случай, когда выбран файл с недопустимым типом (например, pdf)

8 ответов 8

Никогда не используйте $_FILES..["type"] . Содержащаяся в нем информация вообще не проверяется, это пользовательское значение. Проверьте тип самостоятельно. Для изображений exif_imagetype обычно является хорошим выбором:

$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF); $detectedType = exif_imagetype($_FILES["fupload"]["tmp_name"]); $error = !in_array($detectedType, $allowedTypes); $size = getimagesize($filename); if ($size === false) { throw new Exception("{$filename}: Invalid image."); } if ($size > 2500 || $size > 2500) { throw new Exception("{$filename}: Image too large."); } if (!$img = @imagecreatefromstring(file_get_contents($filename))) { throw new Exception("{$filename}: Invalid image content."); }

Проверка по getimagesize() предотвращает некоторые DoS-атаки, потому что нам не нужно пытаться выполнить imagecreatefromstring() из каждого предоставленного пользователем файла, не являющегося файлом изображения или файлом слишком большого размера. К сожалению, согласно документам PHP не может быть полагаться на проверку содержимого типа изображения.

imagecreatefromstring() , наконец, пытается открыть файл как изображение - если это успешно - у нас естьизображение.

2017-07-12 09: 05: 07Z

Это простой однострочный скрипт, который я часто использую.

$image = "/var/www/Core/temp/image.jpg"; $isImage = explode("/", mime_content_type()) == "image";

Обычно я использую mime_content_type (), чтобы получить что-то вроде «image /jpg», а затем взрываю его с помощью «/» и проверяю первый элемент массива, чтобы увидеть, говорит ли он «image».

Я надеюсь, что это работает!

2017-10-18 22: 53: 49Z

В PHP 5.5 я использую эту функцию для получения типа файла и проверки, если изображение:

Function getFileType($file) { return image_type_to_mime_type(exif_imagetype($file)); } // Get file type $file_type = getFileType("path/to/images/test.png"); echo $file_type; // Prints image/png // 1. All images have mime type starting with "image" // 2. No other non-image mime types contain string "image" in it

Тогда вы можете сделать:

If (strpos($filetype, "image") !== false) { // This is an image }

Полный список типов пантомимы: http: //www.sitepoint .com /веб-фонды /MIME типы-полный-лист /

2015-06-11 16: 47: 46Z

Последняя строка близка. Ты можешь использовать: if (mime_content_type($_FILES["fupload"]["tmp_name"]) == "image/gif"){... р>

В случае, над которым я сейчас работаю, мой $_FILES..["type"] сообщает о себе как "text /csv", в то время как mime_content_type() и finfo() (предложенные другими) сообщают "text /plain.". Как указывает @deceze, $_FILES..["type"] полезно знать только о том, какого типа клиент считает файл.

2018-08-09 19: 38: 14Z

ПРЕДУПРЕЖДЕНИЕ : следующий ответ фактически не проверяет тип файла. Он только проверяет имя. Он не подходит для реальных целей безопасности.

РЕДАКТИРОВАТЬ: не используйте этот метод , так как он не выполняет проверку безопасности. Я оставляю этот ответ здесь, чтобы никто не делал такую ​​же ошибку, как я, пытаясь это сделать.

Я попробовал следующее, и это сработало для меня.

22

Обратите внимание, что вам может не потребоваться использование расширений файлов для определения типа файла. например, для загрузки исполняемого файла с расширением.png .Мини-тип также может быть легко подделан вредоносным клиентом для передачи в качестве изображения. Опираясь на эту информацию, это риск для безопасности .

Для размера файла, вы уже используете $_FILES["imagefile"]["size"] ; это нормально, я думаю, но вы будете знать это только в том случае, когда файл был загружен. Тем не менее, нет реального способа проверить это, прежде чем загружать, я боюсь...

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

Не уверен, что вы можете сделать то же самое относительно размера файла, хотя...

Некоторые браузеры могут поддерживать скрытое поле под названием MAX_FILE_SIZE (см. Документацию о file upload); но не уверен, что это действительно поддерживается (никогда не видел раньше, на самом деле, так что, вероятно, не:-()

Как Замечание, вы, вероятно, захотите настроить upload_max_filesize , так что позволяет загружать по крайней мере, большой как вы хотите (по умолчанию он обычно установлен в 2 МБ, поэтому он должен быть в порядке)

2

Php это язык сценариев на стороне сервера, и если изображения находятся на стороне клиента, вы не можете проверить их размер перед загрузки через PHP .

2

Вам нужно две вещи:

ваше расширение проверка регистронезависимы:

If($strtolower($ext == "jpg")){ // do your stuff }

Проверьте, если файл на самом деле содержит изображение. Самый простой способ сделать это FileInfo:

$finfo = finfo_open(FILEINFO_MIME_TYPE); echo finfo_file($finfo, $filename); $finfo_close($finfo);

Альтернативный способ проверки, является ли файл на самом деле изображение загружается в библиотеке изображений, как Gd. Если ваш файл можно успешно загрузить, это изображение.

Имейте в виду, что изображения jpeg могут иметь либо.jpg , либо расширение.jpeg .

3

Вот что я делаю:

If($_FILES["userPicture"]["error"] == 0) { // File was uploaded ok, so it"s ok to proceed with the filetype check. $uploaded_type = exif_imagetype($_FILES["userPicture"]["tmp_name"]); // What we have now is a number representing our file type. switch($uploaded_type) { case "1": $uploaded_type = "gif"; break; case "2": $uploaded_type = "jpg"; break; case "3": $uploaded_type = "png"; break; } }

Edit: Это имеет преимущество работы «в любом браузере», потому что он не зависит от имени файла, или что-нибудь пользователь поставляется, кроме «ошибки» значения файлов массива, который говорит нам, что не было действительно ошибка.

Что такое MIME-тип файла? Как определить MIME-тип файла средствами PHP? Как установить модуль Fileinfo и настроить локальный сервер, сборка Денвер.

MIME - стандарт, описывающий передачу различных типов данных по электронной почте, а также спецификация для кодирования информации и форматирования сообщений таким образом, чтобы их можно было пересылать по Интернету.

Учи матчасть

Как таковой, определение MIME-типа того или иного файла строится на основе его (файла) расширения. Как вы понимает, это достаточно условное определение MIME-типа. Например, файлу image.jpg (даже будь он чем-то иным), по расширению jpg, будет определён MIME-тип: image/jpeg. Конечно, можно проанализировать содержание файла и на его основе определить правильный MIME-тип, но данное решение не входит в рамки моей заметки.

Главное, что сейчас нужно понять, так это необходимость наличия серверного magic.mime файла, где описываются MIME-типы. Как таковой, он входит в состав PHP. Бывает, что и в папках сервера Apache можно найти этот файл. В общем, кто ищет, тот найдёт. По идее, узнать, где находится magic.mime можно считав значение опции mime_magic.magicfile из php.ini. Например:

Однако у меня эта опция ничего не возвращает, тем не менее – попробуйте.

Следует отметить, для того, чтобы определить MIME-тип файла, в PHP имеется модуль Fileinfo. Другими словами, вы всегда можете сориентироваться, имеется ли у вас возможность что-то узнать или нет, по наличию этого модуля. Например:

Так что если модуль есть, то есть и шанс, что оно всё будет работать. В крайнем случае, можно указать путь к своему magic.mime файлу.

Практика

Самым простым способом определения MIME-типа файла средствами PHP является использование php-функции mime_content_type() из модуля Fileinfo. Например:

В результате мы должны получить строку: image/jpeg . Конечно, если файл image.jpg — существует, модуль Fileinfo подключен и magic.mime доступен.

Обратите внимание, что значение функции mime_content_type() должно представлять собой полный путь и имя файла, для чего я использовал конструкцию dirname(__FILE__) . "image.jpg" . Также следует помнить, что эта функция считается устаревшей (англ. deprecated ) и в дальнейшем будет исключена из PHP. Альтернативой может служить решение, написанное с использованием php-функций из того же Fileinfo модуля:

Здесь, функция finfo_open() создаёт Fileinfo ресурс ($finfo). С учётом константы FILEINFO_MIME_TYPE , доступной в PHP версии не ниже 5.3.0, мы сможем получить MIME-тип файла(-ов).

Думаю, уже понятно, что php-функция finfo_file() , используя Fileinfo ресурс ($finfo), возвращает нам информацию для указанного файла ($filename). В нашем случае это MIME-тип: image/jpeg.

Ну и если всё выше сказанное не принесло результата, можно написать свой парсер. Здесь тоже много вариантов. Одним из таковых является парсер magic.mime файла. Не важно где он находится, главное чтоб он был.

Думаю, расписывать, что да как здесь не имеет смысла – и так всё более чем понятно. Хочу лишь обратить ваше внимание на указанный мной путь к файлу mime.types. Как вы уже наверно догадались, речь идёт о локальном сервере. Ещё точнее, о сборке Денвер . И вот тут, мы плавно переходим к установке модуля и настройке сервера.

Установка и настройка

Ещё раз напомню: речь идёт о локальном сервере, сборка Денвер. Как вы понимает, нам понадобится обратиться к файлу php.ini. У меня он находится в папке: С:\WebServer\usr\local\php5\. В нём нам надо подключить два расширения: php_fileinfo.dll и php_mime_magic.dll. Например, так:

Extension=php_fileinfo.dll extension=php_mime_magic.dll

Обращаю внимание на то, что данные расширения должны существовать. У меня они находятся в папке: С:\WebServer\usr\local\php5\ext\.

Mime_magic.debug = On mime_magic.magicfile = "C:\WebServer\usr\local\apache\conf\magic.mime"

Обратите внимание, что для опции mime_magic.magicfile нужно прописать полный путь и имя migic.mime . Вот собственно и всё.

Задача определения расширения возникает в разработке достаточно часто – здесь и , и анализ имеющихся файлов, и поиск файла. В работе с файлами на сервере, есть так же частое решение сохранения файла не с исходным именем, а назначение в качестве имени файла текущего значения TIMESTAMP сервера . Решений у этой задачи существует немало для разных языков программирования. Хотя некоторые решения, в первую очередь, приходящие на ум, иногда приходится дорабатывать из-за того разнообразия имен файлов которые только могут быть. Для файла с именем "myfile.txt" можно смело предложить разбить строку на части разделенные точкой и взять последнюю. Но что делать с файлами "my.file.txt" или в случае, если расширение не указано "myfile"?

В этой статье, рассмотрим такие решения.

Для удобства имя файл зададим в строковой переменной:


$filename = "myfile.txt" ;

// другие варианты имени файла
$filename = "file" ; // не указано расширение
$filename = "my.file.txt" ; // точка в имени файла
$filename = "dir/myfile.txt" ; // имя файла с указанием директории
?>

Самое простое и удобное, на мой взгляд, решение использовать функцию pathinfo() , которая вернет ассоциированный массив, содержащий сведения полном имени, расширении и директории файла. После этого остается только вывести необходимый элемент массива.



$file_info = pathinfo($filename);
return $file_info["extension" ];
}


?>

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


echo pathinfo($filename, PATHINFO_EXTENSION);
?>

Оба варианта корректно вернут значение расширения "txt", кроме случая, где расширение не указано. Там, где расширения нет, будет возвращена пустая строка.

Это решение доступно для PHP, начиная с версии 4.0.3.


Если по причине версии PHP или какой-либо другой причине это решение не доступно, можно использовать традиционное решение – разбивку строки имени файла на части между точками, считая, что последний участок и будет расширением.


function get_file_extension($filename) {
return end(explode("." , $filename));
}

echo get_file_extension($filename);
?>

Здесь, функция explode() разбивает строку на массив из символов, разделенных точками, а функция end() возвращает последний элемент полученного массива.

В этом примере, если расширение не задано явно, т.е. точки в имени файла нет, будет возвращено исходное имя файла. В случае, если расширение есть, оно будет получено корректно.