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

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

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

Считаете, что вопрос пустяковый и все тут просто как 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 сек.

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

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

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

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

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

Задача определения расширения возникает в разработке достаточно часто – здесь и , и анализ имеющихся файлов, и поиск файла. В работе с файлами на сервере, есть так же частое решение сохранения файла не с исходным именем, а назначение в качестве имени файла текущего значения 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() возвращает последний элемент полученного массива.

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