web-dev-qa-db-ja.com

PHPを使用してリモートファイルが存在するかどうかを確認するにはどうすればよいですか?

iffclosefopenタイプのものを見つけると、ページの読み込みが非常に遅くなります。

基本的に私がやろうとしていることは次のとおりです。ウェブサイトのリストがあり、それらの横にファビコンを表示したいです。ただし、サイトにサイトがない場合は、壊れた画像を表示するのではなく、別の画像に置き換えたいと思います。

83
Oliver

CURLOPT_NOBODY経由でHTTP HEADメソッドを使用するようにcurlに指示できます。

多かれ少なかれ

$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);

とにかく、TCP接続の確立と終了ではなく、HTTP転送のコストのみを節約します。ファビコンが小さいため、あまり改善されないかもしれません。

結果がローカルでキャッシュされるのが遅すぎると判明した場合は、良い考えのようです。 HEADは、ファイルの時刻を確認し、ヘッダーで返します。ブラウザのように、アイコンのCURLINFO_FILETIMEを取得できます。キャッシュにURL => [favicon、timestamp]を保存できます。その後、タイムスタンプを比較して、ファビコンを再読み込みできます。

131
Ramon Poca

Piesが言うように、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';   
}
60
Tom Haigh

CoolGooseのソリューションは優れていますが、これは大きなファイルの場合は高速です(1バイトしか読み取ろうとしないため)。

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

これは元の質問への答えではなく、あなたがやろうとしていることをするためのより良い方法です:

実際にサイトのファビコンを直接取得しようとする代わりに(/favicon.png、/favicon.ico、/favicon.gif、または/path/to/favicon.pngの場合もあります)、googleを使用します。

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

できた.

27
Mala

画像を扱う場合は、getimagesizeを使用します。 file_existsとは異なり、この組み込み関数はリモートファイルをサポートします。画像情報(幅、高さ、タイプなど)を含む配列を返します。必要なのは、配列の最初の要素(幅)を確認することだけです。 print_rを使用して配列の内容を出力します

$imageArray = getimagesize("http://www.example.com/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";
}

最も投票された回答の完全な機能:

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
}
15
Pedro Lobito

これは、HTTPステータスコード(404 = not found)を取得することで実行できます。これは、 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 St​​reams

7
hakre

allow_url_fopen設定がセキュリティ上の理由でオフに設定されている場合、URLのチェックにPHPの組み込み関数が機能しない場合があります。 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で始まることも確認します。

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

動作するはずです;)

6
CoolGoose

根本的な解決策は、デフォルトのアイコンの上のdivに、ファビコンを背景画像として表示することです。これにより、破損した画像を表示せずに、すべてのオーバーヘッドがクライアントに置かれます(背景画像の欠落は、すべてのブラウザーで無視されます)。

4
truppo

イメージの存在を確認するには、 exif_imagetypegetimagesize よりも優先されるべきです。

E_NOTICEを抑制するには、エラー制御演算子(@)を付加するだけです。

if (@exif_imagetype($filename)) {
  // Image exist
}

ボーナスとして、IMAGETYPE_XXXからの戻り値(exif_imagetype)を使用すると、image_type_to_mime_type/image_type_to_extensionを使用してMIMEタイプまたはファイル拡張子を取得することもできます。

3
yckart

次を使用できます。

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

画像がURLに存在するかどうかを確認しようとしたときに私のために働いた

3
Rickus Harmse
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!!!";
    }
3
dr.linux

以下を使用できます。

$url=getimagesize(“http://www.flickr.com/photos/27505599@N07/2564389539/”);

if(!is_array($url))
{
   $default_image =”…/directoryFolder/junal.jpg”;
}
2
CP Soni

URIコンテンツはまったく必要ないため、GETではなくHEADリクエストを発行する必要があります。 Piesが上記で述べたように、ステータスコード(200から299の範囲で、オプションで3xxリダイレクトに従うことができます)を確認する必要があります。

回答の質問には、役立つ可能性のある多くのコード例が含まれています。 PHP/Curl:HEAD一部のサイトではリクエストに時間がかかる

1
drdaeman

これは、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';
        }
1
user7018984

ここでget_headers()を使用するすべての回答はGETリクエストを実行しています。 HEADリクエストを行う方がはるかに高速/安価です。

Get_headers()がGETの代わりにHEADリクエストを行うようにするには、これを追加する必要があります。

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を返します。

さらに洗練された代替手段があります。 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/ (元のブログは現在ダウンしています)

1
S Pangborn

ファイルが外部でホストされていない場合、リモートURLをWebサーバー上の絶対パスに変換できます。そうすれば、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を設定する必要があります

0

ファイルがリモートに存在しない場合、これがもっと速いかどうかはわかりません is_file() ですが、試してみてください。

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