私が見つけた最高のもの、 if
fclose
fopen
もの、タイプのものは、ページの読み込みを本当に遅くします。
基本的に私がやろうとしていることは次のとおりです。Webサイトのリストがあり、その横にファビコンを表示したいと思います。ただし、サイトにない場合は、壊れた画像を表示するのではなく、別の画像に置き換えたいと思います。
私が見つけた最高のもの、 if
fclose
fopen
もの、タイプのものは、ページの読み込みを本当に遅くします。
基本的に私がやろうとしていることは次のとおりです。Webサイトのリストがあり、その横にファビコンを表示したいと思います。ただし、サイトにない場合は、壊れた画像を表示するのではなく、別の画像に置き換えたいと思います。
onerror
、たとえばjQueryを使用したソリューションを
回答:
CURLOPT_NOBODYを介してHTTPHEADメソッドを使用するように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 => [ファビコン、タイムスタンプ]を保存できます。次に、タイムスタンプを比較してファビコンをリロードできます。
retcode
400個のコードすべてにエラーがあるため、検証>=
だけではありません>
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';
}
CoolGooseのソリューションは優れていますが、これは大きなファイルの場合は高速です(1バイトしか読み取ろうとしないため)。
if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) {
$image = $default_image;
}
fopen
-リクエストのリターンコードが404の場合、fopenはfalseを返します。
これは元の質問に対する答えではありませんが、あなたがやろうとしていることを行うためのより良い方法です。
実際にサイトのファビコンを直接取得しようとする代わりに(/favicon.png、/favicon.ico、/favicon.gif、さらには/path/to/favicon.pngである可能性があることを考えると、これは非常に苦痛です)、googleを使用します。
<img src="http://www.google.com/s2/favicons?domain=[domain]">
完了。
最も投票された回答の完全な機能:
function remote_file_exists($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); # handles 301/2 redirects
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
}
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
ます。302
リダイレクトを処理するために回答を更新しました。
画像を扱っている場合は、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";
}
exif_imagetype
、そしてそれははるかに高速ですstackoverflow.com/a/38295345/1250044
これは、コンテキストオプションを利用するfile_get_contents
ドキュメントで可能なHTTPステータスコード(404 =見つかりません)を取得することで実行できます。次のコードはリダイレクトを考慮に入れて、最終的な宛先(デモ)のステータスコードを返します。
$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";
リダイレクトをたどりたくない場合は、同様に行うことができます(デモ):
$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";
使用中の関数、オプション、変数のいくつかは、私が書いたブログ投稿でより詳細に説明されています:最初にPHPストリームでHEAD。
$http_response_header
詳細については、php.net / manual / en /reserved.variables.httpresponseheader.phpを参照してください。
セキュリティ上の理由からallow_url_fopen設定がoffに設定されている場合、PHPの組み込み関数はURLのチェックに機能しない可能性があります。後の段階でコードを変更する必要がないため、カールの方が適しています。以下は、有効な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; }
URLがHTTPSで始まることも確認するCURLOPT_SSL_VERIFYPEERオプションに注意してください。
画像の存在を確認するには、がはるかに高速であるため、よりexif_imagetype
も優先する必要がありgetimagesize
ます。
を抑制するにはE_NOTICE
、エラー制御演算子(@
)を前に付けるだけです。
if (@exif_imagetype($filename)) {
// Image exist
}
ボーナスとして、IMAGETYPE_XXX
からの戻り値()を使用しexif_imagetype
て、image_type_to_mime_type
/を使用してmime-typeまたはfile-extensionを取得することもできますimage_type_to_extension
。
次を使用できます。
$file = 'http://mysite.co.za/images/favicon.ico';
$file_exists = (@fopen($file, "r")) ? true : false;
URLに画像が存在するかどうかを確認しようとしたときに私のために働いた
これは、リモートファイルが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';
}
URIの内容はまったく必要ないため、GETではなくHEADリクエストを発行する必要があります。Piesが上で述べたように、ステータスコードを確認する必要があります(200〜299の範囲で、オプションで3xxリダイレクトに従うことができます)。
回答の質問には、役立つ可能性のあるコード例が多数含まれています。PHP/ Curl:一部のサイトではHEADリクエストに長い時間がかかります
さらに洗練された代替手段があります。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()が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を返します。
ファイルがリモートに存在しない場合、is_file()の方が速いかどうかはわかりませんが、試してみることができます。
$favIcon = 'default FavIcon';
if(is_file($remotePath)) {
$favIcon = file_get_contents($remotePath);
}
var_dump(is_file('http://cdn.sstatic.net/stackoverflow/img/sprites.png')); bool(false)
ファイルが外部でホストされていない場合は、リモート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' );
注:この関数を使用するには、WebサーバーにDOCUMENT_ROOTを設定する必要があります
Symfonyフレームワークを使用している場合は、HttpClientInterface
:を使用するはるかに簡単な方法もあります。
private function remoteFileExists(string $url, HttpClientInterface $client): bool {
$response = $client->request(
'GET',
$url //e.g. http://example.com/file.txt
);
return $response->getStatusCode() == 200;
}
HttpClientのドキュメントも非常に優れており、より具体的なアプローチが必要な場合は調べる価値があります:https://symfony.com/doc/current/http_client.html