Ahpub - Компьютер Шаг за Шагом

Проверьте тип файла изображения и размер перед загрузкой файла в PHP. Проверьте тип файла изображения и размер перед загрузкой файла в PHP Установка и настройка

Получить расширение файла - не самая сложная задача. Но подходов к ее решению может быть несколько. Давайте попробуем рассмотреть несколько возможных вариантов и понять принципы их работы.

Считаете, что вопрос пустяковый и все тут просто как 2 пальца? Может быть, только недавно мне встретилась занятная бредострочка с толстенным регулярным выражением и все для того, что бы просто получить несколько символов в конце строки после последней точки. Зачем? Итак, начнем с пяти наиболее распространенных способов. Без использования регулярных выражений (только не подумайте, что я считаю их злом). Писать буду как просто и доступно, это не научная статья, а авторская заметка.

Способ первый

  1. function getExtension1($filename) {
  2. return end (explode (".", $filename));
Логика такова: используя функцию explode() , полученная строка преобразуется в массив строк, границами которых в оригинале был разделитесь «точка». И все бы хорошо, если речь идет об имени файла в стиле «file.txt», но как быть если точек несколько? Для этого end() возвращает последний элемент массива, т.е. то, что было после последней точки.

Способ второй

  1. function getExtension2($filename) {
  2. $path_info = pathinfo ($filename);
  3. return $path_info["extension"];
Здесь на помощь приходит функция pathinfo() , которая возвращает ассоциативный массив, содержащий информацию о нужном нам файле. И если ваша задача узнать не только расширение файла, а так же полный путь к нему и полное имя файла, то этот способ для вас: массив, возвращаемый данной функцией, содержит элементы dirname , basename и extension - в них вся нужная информация.

Способ третий

  1. function getExtension3($filename) {
  2. return substr ($fileName, strrpos ($fileName, ".") + 1);
В данном случае strrpos() возвращает позицию последней точки в строке, а substr() вырезает все символы, начиная с полученной ранее позиции точки, до конца строки. Что бы избавится от самой точки в полученной подстроке, мы увеличивает начало старта на одно смещение вправо (+1).

Способ четвертый

  1. function getExtension4($filename) {
  2. return substr (strrchr ($fileName, "."), 1);
Работает следующим образом: strrchr() возвращает участок строки, следующий за указанным параметром (точкой в нашем случае), после чего substr() отрезает первый символ - точку.

Способ пятый

  1. function getExtension5($filename) {
  2. return array_pop (explode (".", $filename));
Данный способ очень похож на первый. array_pop() - выталкивает элемент в конце массива, end() - устанавливает внутренний указатель массива на последний элемент.

Что работает быстрее? Да, в прочем, на практике результаты выполнения и всех способов примерно одинаковые. Для подтверждения своих догадок провел небольшой тест, прогнав в цикле каждый из вариантов по 50000 раз:
Способ #1: 0.6777439 сек.
Способ #2: 0.5664740 сек.
Способ #3: 0.6604638 сек.
Способ #4: 0.4782789 сек.
Способ #5: 0.6564250 сек.

Какой использовать? Решать вам.

Последняя линия близка. Вы можете использовать: 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)

Что такое 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 . Вот собственно и всё.

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

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

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

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

Загрузка...