Правильный PHP-способ проверить, существует ли внешнее изображение?

Я знаю, что есть ответы по 10 вопросов, но ни один из них не работает для меня безупречно. Я пытаюсь проверить, существует ли внутреннее или внешнее изображение (является ли URL-адрес изображения действительным?).

  • fopen($url, 'r') завершается сбой, если я не использую @fopen():

    Warning: fopen(http://example.com/img.jpg) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in file.php on line 21
    
  • getimagesize($img) не удается, если изображение не существует (PHP 5.3.8):

    Warning: getimagesize() [function.getimagesize]: php_network_getaddresses: getaddrinfo failed
    
  • CURL терпит неудачу, потому что он не поддерживается некоторыми серверами (хотя он присутствует в основном везде).
  • fileExists() терпит неудачу, поскольку он не работает с внешними URL-адресами и не может проверить, имеем ли мы дело с изображением.

Четыре метода, которые являются наиболее распространенными ответами на такой вопрос, являются неправильными. Каким будет правильный способ сделать это?

Ответ 1

getimagesize($img) fails when image doesn't exist: Я не уверен, что вы понимаете, чего хотите...

FROM PHP DOC

Функция getimagesize() будет определять размер любого заданного файла изображения и возвращать размеры вместе с типом файла и текстовой строкой высоты/ширины, которая будет использоваться в обычном теге HTML IMG и соответствующем типе содержимого HTTP.

При ошибке возвращается FALSE.

Пример

$img = array("http://i.stack.imgur.com/52Ha1.png","http://example.com/img.jpg");
foreach ( $img as $v ) {
    echo $v, getimagesize($v) ? " = OK  \n" : " = Not valid \n";
}

Выход

http://i.stack.imgur.com/52Ha1.png = OK  
http://example.com/img.jpg = Not valid 

getimagesize работает просто отлично

Изменить

@Paul. но ваш вопрос в основном говорит: "Как я могу справиться с этим, поэтому я не получу ошибку при возникновении ошибки". И ответ на это "вы не можете". Поскольку все эти функции вызывают ошибку при возникновении ошибки. Поэтому (если вы не хотите ошибки) вы его подавляете. Ничего из этого не должно иметь значения в производстве, потому что вы все равно не должны отображать ошибки;-) - DaveRandom

Ответ 2

Этот код на самом деле проверяет файл... Но он работает для изображений!

$url = "http://www.myfico.com/Images/sample_overlay.gif";
$header_response = get_headers($url, 1);
if ( strpos( $header_response[0], "404" ) !== false )
{
   // FILE DOES NOT EXIST
} 
else 
{
   // FILE EXISTS!!
}

Ответ 3

function checkExternalFile($url)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $retCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return $retCode;
}

$fileExists = checkExternalFile("http://example.com/your/url/here.jpg");

// $fileExists > 400 = not found
// $fileExists = 200 = found.

Ответ 4

Если вы используете PHP >= 5.0.0, вы можете передать дополнительный параметр в fopen, чтобы указать параметры контекста для HTTP, среди которых игнорировать коды состояния отказа.

$contextOptions = array( 'http' => array('ignore_errors' => true));

$context = stream_context_create($contextOptions);

$handle = fopen($url, 'r', false, $context);

Ответ 5

Для этого вы можете использовать пакет PEAR/HTTP_Request2. Вы можете найти здесь

Вот пример. В примере предполагается, что вы правильно установили или загрузили пакет HTTP_Request2. Он использует адаптер сокета старого стиля, а не завиток.

<?php

require_once 'HTTP/Request2.php';
require_once 'HTTP/Request2/Adapter/Socket.php';

$request = new HTTP_Request2 (
    $your_url, 
    HTTP_Request2::METHOD_GET,
    array('adapter' => new HTTP_Request2_Adapter_Socket())
);

switch($request->send()->getResponseCode()) {

    case 404 : 
        echo 'not found';
        break;

    case 200 :
        echo 'found';
        break;

    default :
        echo 'needs further attention';

}

Ответ 6

Используйте fsockopen, подключитесь к серверу, отправьте запрос HEAD и посмотрите, какой статус вы вернетесь.

Единственный раз, когда вам нужно знать о проблемах, - если домен не существует.

Пример кода:

$file = "http://example.com/img.jpg";
$path = parse_url($file);
$fp = @fsockopen($path['host'],$path['port']?:80);
if( !$fp) echo "Failed to connect... Either server is down or host doesn't exist.";
else {
  fputs($fp,"HEAD ".$file." HTTP/1.0\r\n"
     ."Host: ".$path['host']."\r\n\r\n");
  $firstline = fgets($fp);
  list(,$status,$statustext) = explode(" ",$firstline,3);
  if( $status == 200) echo "OK!";
  else "Status ".$status." ".$statustext."...";
}

Ответ 7

Я нашел попытку поймать лучшее решение для этого. Он отлично работает со мной.

try{
      list($width, $height) = getimagesize($h_image->image_url);
   }
catch (Exception $e)
    {
    }

Ответ 8

Я знаю, что вы написали "без завитки", но все же кто-то может найти это полезное:

function curl_head($url) {

    $ch = curl_init($url);

    //curl_setopt($ch, CURLOPT_USERAGENT, 'Your user agent');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1); # get headers
    curl_setopt($ch, CURLOPT_NOBODY, 1); # omit body
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); # do SSL check
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); # verify domain within cert
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); # follow "Location" redirs
    //curl_setopt($ch, CURLOPT_TIMEOUT_MS, 700); # dies after 700ms

    $result = curl_exec($ch);

    curl_close($ch);

    return $result;
}

print_r(curl_head('https://www.example.com/image.jpg'));

В возвращаемом массиве заголовков вы увидите следующее HTTP/1.1 200 OK или HTTP/1.1 404 Not Found. Вы можете выполнять несколько параллельных запросов с помощью curl multi.

Ответ 9

Существует несколько этапов, нет единого решения:

  • Подтвердить URL
  • Проверьте, доступен ли файл (можно сделать непосредственно с шага 3)
  • Загрузите изображение в файл tmp.
  • Используйте getimagesize, чтобы проверить размер изображения.

Для такого рода работ вы можете поймать исключения и хорошо их обработать, чтобы определить свой ответ. В этом случае вы могли бы даже подавлять ошибки, потому что они предполагали, что их трюк может потерпеть неудачу. Поэтому вы правильно обрабатываете ошибки.

Потому что не удается выполнить 100% проверку, не загрузив фактическое изображение. Таким образом, требуются шаги 1 и 2, 3 и 4 необязательные для более окончательного ответа.