PHPを使用してURLを指定すると、それが画像であるかどうかをどのように判断できますか?
URLのコンテキストはありません-プレーンテキストファイルの中央にあるか、または文字列だけです。
これはページ上の多くのURLに対して呼び出される可能性があるため、高いオーバーヘッド(URLのコンテンツの読み取りなど)は必要ありません。この制限を考えると、すべての画像を特定することは必須ではありませんが、かなり良い推測をお願いします。
現時点ではファイル拡張子を見ているだけですが、これよりも良い方法があるはずです。
私が現在持っているものは次のとおりです。
function isImage( $url )
{
$pos = strrpos( $url, ".");
if ($pos === false)
return false;
$ext = strtolower(trim(substr( $url, $pos)));
$imgExts = array(".gif", ".jpg", ".jpeg", ".png", ".tiff", ".tif"); // this is far from complete but that's always going to be the case...
if ( in_array($ext, $imgExts) )
return true;
return false;
}
編集:エミールHの答えからのテクニックを使用して、ここで他の誰かがそれが最終関数である場合に便利です:
function isImage($url)
{
$params = array('http' => array(
'method' => 'HEAD'
));
$ctx = stream_context_create($params);
$fp = @fopen($url, 'rb', false, $ctx);
if (!$fp)
return false; // Problem with url
$meta = stream_get_meta_data($fp);
if ($meta === false)
{
fclose($fp);
return false; // Problem reading data from url
}
$wrapper_data = $meta["wrapper_data"];
if(is_array($wrapper_data)){
foreach(array_keys($wrapper_data) as $hh){
if (substr($wrapper_data[$hh], 0, 19) == "Content-Type: image") // strlen("Content-Type: image") == 19
{
fclose($fp);
return true;
}
}
}
fclose($fp);
return false;
}
HTTP HEAD リクエストを使用して、content-typeを確認できます。これは良い妥協かもしれません。 PHP Streams を使用して実行できます。 Wez Furlongには、このアプローチを使用して投稿リクエストを送信する方法を示す article がありますが、代わりにHEADリクエストを送信するように簡単に調整できます。ヘッダーを取得できます stream_get_meta_data() を使用したhttp応答から。
もちろん、これは実際には100%ではありません。一部のサーバーは、誤ったヘッダーを送信します。ただし、スクリプトを介して画像が配信され、正しいファイル拡張子が利用できない場合は処理します。本当に確実にする唯一の方法は、イメージを実際に取得することです-thomasrutterが示唆するように、イメージのすべて、または最初の数バイトのいずれかです。
if(is_array(getimagesize($urlImg)))
echo 'Yes it is an image!';
いくつかの異なるアプローチがあります。
ファイルの先頭でマジックナンバーを探してコンテンツを探ります。たとえば、GIFはGIF87またはGIF89をファイルの最初の5バイトとして(ASCIIで)使用します。残念ながら、画像にエラーがあるかどうか、または画像に悪意のあるコンテンツが含まれているかどうかはわかりません。さまざまな種類の画像ファイルのマジックナンバーを次に示します(これらを自由に使用してください)。
"\ xff\xd8\xff" => 'image/jpeg'、 "\ x89PNG\x0d\x0a\x1a\x0a" => 'image/png'、 "II *\x00" => 'image/tiff'、 "MM\x00 *" => 'image/tiff'、 "\ x00\x00\x01\x00" = > 'image/ico'、 "\ x00\x00\x02\x00" => 'image/ico'、 "GIF89a" => 'image/gif'、 "GIF87a" => 'image/gif'、 "BM" => 'image/bmp'、
このようなコンテンツをスニッフィングすることは、おそらく要件に最も適合するでしょう。ファイルの最初の数バイトを読み取るだけでダウンロードする必要があります(ヘッダーを貼り付けます)。
Gdライブラリを使用してイメージをロードし、エラーなくロードされるかどうかを確認します。これにより、イメージが有効であるかどうか、エラーが発生しているかどうかがわかります。残念ながら、完全なイメージをダウンロードする必要があるため、これはおそらく要件に適合しません。
残念ながら、ファイルは有効な画像であると同時に、Javaとして実行される有害なコンテンツを含むZipファイルである可能性があります- GIFARエクスプロイト 。Gdなどのライブラリに画像をロードし、その上でわずかなフィルタを実行することにより、この脆弱性をほぼ確実に防ぐことができます。 )そしてそれを新しいファイルに保存しますwithoutメタデータを転送します。
コンテンツタイプだけで何かがイメージであるかどうかを判断しようとすると、ファイル拡張子をチェックするのとほぼ同じくらい信頼性が低くなります。 <img要素を使用して画像を読み込むと、ブラウザはマジックストリングを探ります。
エミールHの答えに加えて:
get_headers()
を使用してファイル全体をダウンロードせずにgetimagesize()
でURLのコンテンツタイプを確認する
$url_headers=get_headers($url, 1);
if(isset($url_headers['Content-Type'])){
$type=strtolower($url_headers['Content-Type']);
$valid_image_type=array();
$valid_image_type['image/png']='';
$valid_image_type['image/jpg']='';
$valid_image_type['image/jpeg']='';
$valid_image_type['image/jpe']='';
$valid_image_type['image/gif']='';
$valid_image_type['image/tif']='';
$valid_image_type['image/tiff']='';
$valid_image_type['image/svg']='';
$valid_image_type['image/ico']='';
$valid_image_type['image/icon']='';
$valid_image_type['image/x-icon']='';
if(isset($valid_image_type[$type])){
//do something
}
}
編集:一般的な画像拡張子を持つ静的画像用。
<?php
$imgExts = array("gif", "jpg", "jpeg", "png", "tiff", "tif");
$url ='path/to/image.png';
$urlExt = pathinfo($url, PATHINFO_EXTENSION);
if (in_array($urlExt, $imgExts)) {
echo 'Yes, '.$url.' is an Image';
}
?>
与えられた答えに似ていますが、ロジックがわずかに異なります。
_$headers = @get_headers($url, 1); // @ to suppress errors. Remove when debugging.
if (isset($headers['Content-Type'])) {
if (strpos($headers['Content-Type'], 'image/') === FALSE) {
// Not a regular image (including a 404).
}
else {
// It's an image!
}
}
else {
// No 'Content-Type' returned.
}
_
@は エラー制御演算子 です。
ユースケースがhaystackで見つかった場合、strpos($headers['Content-Type'], 'image/')
はユースケースで_=== FALSE
_を返すため、条件で「厳密な」演算子_0
_を使用したことに注意してください。誤ってFALSE
として解釈される_==
_を使用した型キャスト。
exif_imagetypeを使用して画像タイプを確認できるため、他のコンテンツタイプは許可されません。画像のみを許可し、いくつかの画像タイプに制限できます。次のサンプルコードは、GIF画像タイプを許可する方法を示しています。
if (exif_imagetype('image.gif') != IMAGETYPE_GIF) {
echo 'The picture is not a gif';
}
次の画像タイプを使用できます。
IMAGETYPE_GIF
IMAGETYPE_JPEG
IMAGETYPE_PNG
IMAGETYPE_SWF
IMAGETYPE_PSD
IMAGETYPE_BMP
IMAGETYPE_TIFF_II (intel byte order)
IMAGETYPE_TIFF_MM (Motorola byte order)
IMAGETYPE_JPC
IMAGETYPE_JP2
IMAGETYPE_JPX
IMAGETYPE_JB2
IMAGETYPE_SWC
IMAGETYPE_IFF
IMAGETYPE_WBMP
IMAGETYPE_XBM
IMAGETYPE_ICO
詳細: リンク
壊れたまたは見つからない画像リンクの高速ソリューション
。
if(checkRemoteFile($imgurl))
{
//found url, its mean
echo "this is image";
}
function checkRemoteFile($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
// don't download content
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if(curl_exec($ch)!==FALSE)
{
return true;
}
else
{
return false;
}
}
注:この現在のコードは、壊れたまたは見つからないURLイメージを識別するのに役立ちます。これは、イメージタイプまたはヘッダーを識別するのに役立ちません。