Лучшее, что я мог найти, например, if
fclose
fopen
типа, делает загрузку страницы очень медленно.
В основном я пытаюсь сделать следующее: у меня есть список веб-сайтов, и я хочу показать их значки рядом с ними. Однако, если сайт не имеет одного, я бы хотел заменить его другим изображением, а не отображать сломанное изображение.
Вы можете указать curl использовать метод HTTP HEAD через CURLOPT_NOBODY.
Более или менее
$ch = curl_init("http://www.example.com/favicon.ico"); curl_setopt($ch, CURLOPT_NOBODY, true); curl_exec($ch); $retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // $retcode >= 400 -> not found, $retcode = 200, found. curl_close($ch);
В любом случае, вы сохраняете только стоимость передачи HTTP, а не установление и закрытие TCP-соединения. И, будучи небольшим значком, вы можете не видеть большого улучшения.
Кэширование результата локально кажется хорошей идеей, если оно окажется слишком медленным. HEAD проверяет время файла и возвращает его в заголовках. Вы можете сделать как браузеры и получить CURLINFO_FILETIME значка. В вашем кеше вы можете сохранить URL => [favicon, timestamp]. Затем вы можете сравнить временную метку и перезагрузить значок.
Как говорят пироги, вы можете использовать cURL. Вы можете получить cURL только для того, чтобы дать вам заголовки, а не тело, которое могло бы сделать его быстрее. Плохой домен всегда может занять некоторое время, потому что вы будете ждать запроса на тайм-аут; вы, вероятно, можете изменить длину таймаута, используя cURL.
Вот пример:
function remoteFileExists($url) { $curl = curl_init($url); //don't fetch the actual page, you only want to check the connection is ok curl_setopt($curl, CURLOPT_NOBODY, true); //do request $result = curl_exec($curl); $ret = false; //if request did not fail if ($result !== false) { //if request was ok, check response code $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($statusCode == 200) { $ret = true; } } curl_close($curl); return $ret; } $exists = remoteFileExists('http://stackoverflow.com/favicon.ico'); if ($exists) { echo 'file exists'; } else { echo 'file does not exist'; }
Решение CoolGoose является хорошим, но это происходит быстрее для больших файлов (поскольку он только пытается прочитать 1 байт):
if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) { $image = $default_image; }
Это не ответ на ваш первоначальный вопрос, а лучший способ сделать то, что вы пытаетесь сделать:
Вместо того, чтобы на самом деле пытаться получить иконку сайта напрямую (что является королевской болью, если она может быть /favicon.png, /favicon.ico, /favicon.gif или даже /path/to/favicon.png), используйте google:
<img src="http://www.google.com/s2/favicons?domain=[domain]">
Готово.
Если вы имеете дело с изображениями, используйте getimagesize. В отличие от file_exists, эта встроенная функция поддерживает удаленные файлы. Он вернет массив, содержащий информацию об изображении (ширина, высота, тип..etc). Все, что вам нужно сделать, это проверить первый элемент в массиве (ширину). используйте print_r для вывода содержимого массива
$imageArray = getimagesize("http://img.ruphp.com/php/image.jpg"); if($imageArray[0]) { echo "it's an image and here is the image's info<br>"; print_r($imageArray); } else { echo "invalid image"; }
if (false === file_get_contents("http://example.com/path/to/image")) { $image = $default_image; }
Должно сработать 😉
Это можно сделать, получив код состояния HTTP (404 = не найден), что возможно при использовании file_get_contents
использованием опций контекста. Следующий код учитывает переадресацию и возвращает код состояния конечного пункта назначения ( Demo ):
$url = 'http://example.com/'; $code = FALSE; $options['http'] = array( 'method' => "HEAD", 'ignore_errors' => 1 ); $body = file_get_contents($url, NULL, stream_context_create($options)); foreach($http_response_header as $header) sscanf($header, 'HTTP/%*d.%*d %d', $code); echo "Status code: $code";
Если вы не хотите следовать переадресации, вы можете сделать это аналогично ( Demo ):
$url = 'http://example.com/'; $code = FALSE; $options['http'] = array( 'method' => "HEAD", 'ignore_errors' => 1, 'max_redirects' => 0 ); $body = file_get_contents($url, NULL, stream_context_create($options)); sscanf($http_response_header[0], 'HTTP/%*d.%*d %d', $code); echo "Status code: $code";
Некоторые из используемых функций, опций и переменных объясняются более подробно в блоге, который я написал: HEAD сначала с потоками PHP .
Встроенные функции PHP могут не работать для проверки URL-адреса, если параметр allow_url_fopen отключен по соображениям безопасности. Curl – лучший вариант, поскольку нам не нужно будет менять наш код на более позднем этапе. Ниже приведен код, который я использовал для проверки действительного URL:
$url = str_replace(' ', '%20', $url); $ch = curl_init($url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_NOBODY, true); curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if($httpcode>=200 && $httpcode<300){ return true; } else { return false; }
Не забудьте отметить параметр CURLOPT_SSL_VERIFYPEER, который также проверяет URL-адрес, начинающийся с HTTPS.
Радикальным решением было бы отображать значки в качестве фоновых изображений в div над вашим значком по умолчанию. Таким образом, все накладные расходы будут размещены на клиенте, пока не будут отображаться сломанные изображения (отсутствующие фоновые изображения игнорируются во всех браузерах AFAIK).
Полная функция завитки наиболее проголосовавшего ответа:
function remote_file_exists($url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_NOBODY, true); curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if( $httpCode == 200 ){return true;} }
Вы можете использовать его следующим образом:
if(remote_file_exists($url)) { //file exists, do something }
function remote_file_exists($url){ return(bool)preg_match('~HTTP/1\.\d\s+200\s+OK~', @current(get_headers($url))); } $ff = "http://www.emeditor.com/pub/emed32_11.0.5.exe"; if(remote_file_exists($ff)){ echo "file exist!"; } else{ echo "file not exist!!!"; }
Вы можете использовать :
$url=getimagesize(“http://www.flickr.com/photos/27505599@N07/2564389539/”); if(!is_array($url)) { $default_image =”…/directoryFolder/junal.jpg”; }
Вы можете использовать следующее:
$file = 'http://mysite.co.za/images/favicon.ico'; $file_exists = (@fopen($file, "r")) ? true : false;
Работала для меня, пытаясь проверить, существует ли изображение в URL-адресе
Вы должны вызывать HEAD-запросы, а не GET, потому что вам совсем не нужно содержимое URI. Как упоминалось выше, вы должны проверить код состояния (в диапазонах 200-299, и вы можете, возможно, следовать переадресации 3xx).
Ответы на вопросы содержат много примеров кода, которые могут быть полезны: PHP / Curl: HEAD Request занимает много времени на некоторых сайтах
Есть еще более сложная альтернатива. Вы можете проверить все клиентские стороны с помощью трюка JQuery.
$('a[href^="http://"]').filter(function(){ return this.hostname && this.hostname !== location.hostname; }).each(function() { var link = jQuery(this); var faviconURL = link.attr('href').replace(/^(http:\/\/[^\/]+).*$/, '$1')+'/favicon.ico'; var faviconIMG = jQuery('<img src="favicon.png" alt="" />')['appendTo'](link); var extImg = new Image(); extImg.src = faviconURL; if (extImg.complete) faviconIMG.attr('src', faviconURL); else extImg.onload = function() { faviconIMG.attr('src', faviconURL); }; });
Из http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (исходный блог в настоящее время отсутствует)
все ответы здесь, которые используют get_headers (), выполняют запрос GET. Гораздо быстрее / дешевле просто выполнить запрос HEAD.
Чтобы убедиться, что get_headers () выполняет запрос HEAD вместо GET, вы должны добавить следующее:
stream_context_set_default( array( 'http' => array( 'method' => 'HEAD' ) ) );
поэтому, чтобы проверить, существует ли файл, ваш код будет выглядеть примерно так:
stream_context_set_default( array( 'http' => array( 'method' => 'HEAD' ) ) ); $headers = get_headers('http://img.ruphp.com/php/file.jpg', 1); $file_found = stristr($headers[0], '200');
Очевидно, файл file_found вернет либо false, либо true.
Чтобы проверить наличие изображений, exif_imagetype
должен быть предпочтительнее getimagesize
, так как он намного быстрее.
Чтобы подавить E_NOTICE
, просто добавьте оператор управления ошибкой ( @
).
if (@exif_imagetype($filename)) { // Image exist }
В качестве бонуса, с возвращаемым значением ( IMAGETYPE_XXX
) из exif_imagetype
мы могли бы также получить MIME-тип или расширение файла с помощью image_type_to_mime_type
/ image_type_to_extension
.
Не знаю, быстрее ли это, когда файл не существует удаленно, is_file () , но вы можете дать ему шанс.
$favIcon = 'default FavIcon'; if(is_file($remotePath)) { $favIcon = file_get_contents($remotePath); }
Это работает для меня, чтобы проверить, существует ли удаленный файл в PHP:
$url = 'https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico'; $header_response = get_headers($url, 1); if ( strpos( $header_response[0], "404" ) !== false ) { echo 'File does NOT exist'; } else { echo 'File exists'; }