Используя PHP, учитывая URL-адрес, как определить, является ли это образ?
Нет контекста для URL-адреса – он находится только в середине простого текстового файла или, может быть, просто строка сама по себе.
Мне не нужны высокие накладные расходы (например, чтение содержимого URL-адреса), поскольку это может быть вызвано для многих URL-адресов на странице. Учитывая это ограничение, не обязательно, чтобы все изображения были идентифицированы, но я хотел бы получить довольно хорошее предположение.
На данный момент я просто смотрю на расширение файла, но похоже, что должен быть лучший способ, чем это.
Вот что я сейчас имею:
function isImage( $url ) { $pos = strrpos( $url, "."); if ($pos === false) return false; $ext = strtolower(trim(substr( $url, $pos))); $imgExts = array(".gif", ".jpg", ".jpeg", ".png", ".tiff", ".tif"); // this is far from complete but that's always going to be the case... if ( in_array($ext, $imgExts) ) return true; return false; }
Edit: В случае, если это полезно для кого-то еще, это последняя функция, использующая технику из ответа Эмиля H:
function isImage($url) { $params = array('http' => array( 'method' => 'HEAD' )); $ctx = stream_context_create($params); $fp = @fopen($url, 'rb', false, $ctx); if (!$fp) return false; // Problem with url $meta = stream_get_meta_data($fp); if ($meta === false) { fclose($fp); return false; // Problem reading data from url } $wrapper_data = $meta["wrapper_data"]; if(is_array($wrapper_data)){ foreach(array_keys($wrapper_data) as $hh){ if (substr($wrapper_data[$hh], 0, 19) == "Content-Type: image") // strlen("Content-Type: image") == 19 { fclose($fp); return true; } } } fclose($fp); return false; }
Вы можете использовать запрос HTTP HEAD и проверить тип содержимого. Это может быть хорошим компромиссом. Это можно сделать с помощью PHP Streams . У Wez Furlong есть статья, в которой показано, как использовать этот подход для отправки почтовых запросов, но он может быть легко адаптирован для отправки запросов HEAD. Вы можете получить заголовки из ответа HTTP с помощью stream_get_meta_data () .
Конечно, это не на самом деле 100%. Некоторые серверы отправляют неверные заголовки. Однако он будет обрабатывать случаи, когда изображения доставляются через скрипт, а правильное расширение файла недоступно. Единственный способ быть действительно уверенным в том, чтобы фактически получить изображение – либо все, либо первые несколько байтов, как было предложено thomasrutter.
Существует несколько разных подходов.
Понюхайте контент, ища волшебное число в начале файла. Например, GIF использует GIF87 или GIF89 в качестве первых пяти байтов файла (в ascii). К сожалению, это не может сказать вам, есть ли ошибка в изображении или изображение содержит вредоносный контент. Вот несколько магических чисел для различных типов файлов изображений (не стесняйтесь их использовать):
"\ xff \ xd8 \ xff" => 'image / jpeg', "\ x89PNG \ x0d \ x0a \ x1a \ x0a" => 'image / png', "II * \ x00" => 'image / tiff', «MM \ x00 *" => 'image / tiff', "\ x00 \ x00 \ x01 \ x00" => 'image / ico', "\ x00 \ x00 \ x02 \ x00" => 'image / ico', «GIF89a» => 'image / gif', "GIF87a" => 'image / gif', «BM» => 'image / bmp',
Обнюхать контент, подобный этому, вероятно, будет лучше соответствовать вашим требованиям; вам нужно будет только прочитать и, следовательно, загрузить первые несколько байтов файла (за заголовком).
Загрузите изображение с помощью библиотеки GD, чтобы узнать, загружается ли он без ошибок. Это может сказать вам, является ли изображение действительным, без ошибок или нет. К сожалению, это, вероятно, не соответствует вашим требованиям, потому что это требует загрузки полного изображения.
К сожалению, файл может быть как допустимым, так и ZIP-файлом, содержащим вредоносное содержимое, которое может быть выполнено как Java вредоносным сайтом – см. Эксплойт GIFAR . Вы почти наверняка предотвратите эту уязвимость, загрузив изображение в библиотеке, например GD, и произнесете на ней какой-то нетривиальный фильтр, например, смягчая или затачивая его крошечным количеством (т. Е. Используя фильтр свертки) и сохраняя его в новом файле без переноса любые метаданные.
Попытка определить, является ли что-то изображение одним только своим типом контента, является довольно ненадежным, почти таким же ненадежным, как проверка расширения файла. При загрузке изображения с помощью элемента <img браузеры нюхают магическую строку.
if(is_array(getimagesize($urlImg))) echo 'Yes it's an image!';
В дополнение к ответу Эмиля Х:
Используя get_headers()
чтобы проверить тип содержимого URL- getimagesize()
не загружая весь файл с помощью getimagesize()
$url_headers=get_headers($url, 1); if(isset($url_headers['Content-Type'])){ $type=strtolower($url_headers['Content-Type']); $valid_image_type=array(); $valid_image_type['image/png']=''; $valid_image_type['image/jpg']=''; $valid_image_type['image/jpeg']=''; $valid_image_type['image/jpe']=''; $valid_image_type['image/gif']=''; $valid_image_type['image/tif']=''; $valid_image_type['image/tiff']=''; $valid_image_type['image/svg']=''; $valid_image_type['image/ico']=''; $valid_image_type['image/icon']=''; $valid_image_type['image/x-icon']=''; if(isset($valid_image_type[$type])){ //do something } }
Изменить: для статических изображений с популярным расширением изображения.
<?php $imgExts = array("gif", "jpg", "jpeg", "png", "tiff", "tif"); $url ='path/to/image.png'; $urlExt = pathinfo($url, PATHINFO_EXTENSION); if (in_array($urlExt, $imgExts)) { echo 'Yes, '.$url.' is an Image'; } ?>
мы можем использовать exif_imagetype для проверки типа изображения, поэтому он не допускает каких-либо других типов содержимого. Это разрешает только изображения, и мы можем ограничить их несколькими типами изображений, после примера кода показано, как разрешить тип изображения GIF.
if (exif_imagetype('image.gif') != IMAGETYPE_GIF) { echo 'The picture is not a gif'; }
Вы можете использовать следующие типы изображений,
IMAGETYPE_GIF IMAGETYPE_JPEG IMAGETYPE_PNG IMAGETYPE_SWF IMAGETYPE_PSD IMAGETYPE_BMP IMAGETYPE_TIFF_II (intel byte order) IMAGETYPE_TIFF_MM (motorola byte order) IMAGETYPE_JPC IMAGETYPE_JP2 IMAGETYPE_JPX IMAGETYPE_JB2 IMAGETYPE_SWC IMAGETYPE_IFF IMAGETYPE_WBMP IMAGETYPE_XBM IMAGETYPE_ICO
подробнее: ссылка
Как и в случае с некоторым ответом, но с немного иной логикой.
$headers = @get_headers($url, 1); // @ to suppress errors. Remove when debugging. if (isset($headers['Content-Type'])) { if (strpos($headers['Content-Type'], 'image/') === FALSE) { // Not a regular image (including a 404). } else { // It's an image! } } else { // No 'Content-Type' returned. }
@ – оператор управления ошибками .
Обратите внимание, что мы использовали «строгий» оператор === FALSE
в условии, потому что strpos($headers['Content-Type'], 'image/')
возвращает 0
в нашем случае, если игла находится в стоге сена. С типом casting с использованием ==
, который ошибочно будет интерпретироваться как FALSE
.
Быстрое решение для сломанной или не найденной ссылки изображения
я рекомендую вам, чтобы не использовать getimagesize (), потому что он будет загружать 1-й снимок, тогда он будет проверять размер изображения +, если это не будет изображение, тогда он будет генерировать исключение, поэтому используйте ниже код
if(checkRemoteFile($imgurl)) { //found url, its mean echo "this is image"; } function checkRemoteFile($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); // don't download content curl_setopt($ch, CURLOPT_NOBODY, 1); curl_setopt($ch, CURLOPT_FAILONERROR, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if(curl_exec($ch)!==FALSE) { return true; } else { return false; } }
Примечание: этот текущий код поможет вам идентифицировать сломанное или не найденное изображение URL-адреса, это не поможет вам определить тип изображения или заголовки