Как можно проверить, существует ли удаленный файл с помощью PHP?

Лучшее, что я мог найти, вещь типа if fclose fopen, делает загрузку страницы очень медленной.

В основном я пытаюсь сделать следующее: у меня есть список веб-сайтов, и я хочу показать их значки рядом с ними. Однако, если сайт не имеет одного, я хотел бы заменить его другим изображением, а не отображать сломанное изображение.

Ответ 1

Вы можете указать curl использовать метод HEAD HTTP через 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]. Затем вы можете сравнить временную метку и перезагрузить значок.

Ответ 2

Как говорят пироги, вы можете использовать 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';   
}

Ответ 3

Решение CoolGoose хорошее, но это происходит быстрее для больших файлов (поскольку он только пытается прочитать 1 байт):

if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) {
    $image = $default_image;
}

Ответ 4

Это не ответ на ваш исходный вопрос, но лучший способ сделать то, что вы пытаетесь сделать:

Вместо того, чтобы на самом деле пытаться получить сайт favicon напрямую (что является королевской болью, учитывая, что это может быть /favicon.png,/favicon.ico,/favicon.gif или даже /path/to/favicon.png), используйте google:

<img src="http://www.google.com/s2/favicons?domain=[domain]">

Готово.

Ответ 5

Если вы имеете дело с изображениями, используйте getimagesize. В отличие от file_exists, эта встроенная функция поддерживает удаленные файлы. Он вернет массив, содержащий информацию об изображении (ширина, высота, тип..etc). Все, что вам нужно сделать, это проверить первый элемент в массиве (ширину). используйте print_r для вывода содержимого массива

$imageArray = getimagesize("http://www.example.com/image.jpg");
if($imageArray[0])
{
    echo "it an image and here is the image info<br>";
    print_r($imageArray);
}
else
{
    echo "invalid image";
}

Ответ 6

Полная функция наиболее проголосовавшего ответа:

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
}

Ответ 7

Это можно сделать, получив код состояния HTTP (404 = не найден), что возможно с помощью file_get_contents Docs, используя вариантов контекста. Следующий код учитывает переадресацию и возвращает код состояния конечного адресата (Демо):

$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.

Ответ 8

if (false === file_get_contents("http://example.com/path/to/image")) {
    $image = $default_image;
}

Должен работать;)

Ответ 9

Встроенные функции 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.

Ответ 10

Радикальным решением будет отображение значков в качестве фоновых изображений в div над вашим значком по умолчанию. Таким образом, все накладные расходы будут размещены на клиенте, пока не будут отображаться сломанные изображения (отсутствующие фоновые изображения игнорируются во всех браузерах AFAIK).

Ответ 11

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!!!";
    }

Ответ 12

Вы можете использовать следующее:

$file = 'http://mysite.co.za/images/favicon.ico';
$file_exists = (@fopen($file, "r")) ? true : false;

Работала для меня при попытке проверить, существует ли изображение в URL

Ответ 13

Чтобы проверить наличие изображений, 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.

Ответ 14

Вы можете использовать:

$url=getimagesize("http://www.flickr.com/photos/[email protected]/2564389539/");

if(!is_array($url))
{
   $default_image ="…/directoryFolder/junal.jpg";
}

Ответ 15

Вы должны вызывать HEAD-запросы, а не GET, потому что вам совсем не нужно содержимое URI. Как уже говорилось выше, вы должны проверить код состояния (в диапазонах 200-299, и вы можете, возможно, следовать перенаправлениям 3xx).

Ответ на вопрос содержит много примеров кода, которые могут быть полезны: PHP/Curl: HEAD Request занимает много времени на некоторых сайтах

Ответ 16

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

Ответ 17

все ответы здесь, которые используют 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://website.com/dir/file.jpg', 1);
$file_found = stristr($headers[0], '200');

$file_found, очевидно, вернет либо false, либо true.

Ответ 18

Это работает для меня, чтобы проверить, существует ли удаленный файл в 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';
        }

Ответ 19

Не знаю, быстрее ли это, когда файл не существует удаленно, is_file(), но вы могли бы дать его выстрел.

$favIcon = 'default FavIcon';
if(is_file($remotePath)) {
   $favIcon = file_get_contents($remotePath);
}

Ответ 20

Если файл не размещен снаружи, вы можете перевести удаленный URL-адрес в абсолютный путь на вашем веб-сервере. Таким образом, вам не нужно вызывать CURL или file_get_contents и т.д.

function remoteFileExists($url) {

    $root = realpath($_SERVER["DOCUMENT_ROOT"]);
    $urlParts = parse_url( $url );

    if ( !isset( $urlParts['path'] ) )
        return false;

    if ( is_file( $root . $urlParts['path'] ) )
        return true;
    else
        return false;

}

remoteFileExists( 'https://www.yourdomain.com/path/to/remote/image.png' );

Примечание: ваш веб-сервер должен заполнить DOCUMENT_ROOT, чтобы использовать эту функцию

Ответ 21

Вы можете использовать файловую систему: использовать Symfony\Component\Filesystem\Filesystem; использовать Symfony\Component\Filesystem\Exception\IOExceptionInterface;

и проверьте $ fileSystem = new Filesystem(); если ($fileSystem-> существует ('path_to_file') == true) {...