アップロードしたファイルが画像ファイル(png、jpg、jpeg、gif、bmpなど)か、別のファイルかを確認したい。問題は、Uploadifyを使用してファイルをアップロードしていることです。これにより、MIMEタイプが変更され、アップロードするファイルタイプに関係なく、MIMEタイプとして「テキスト/ 8進数」などが表示されます。
PHPを使用してファイル拡張子を確認する以外に、アップロードされたファイルが画像かどうかを確認する方法はありますか?
非画像ではサイズにゼロを返す getimagesize()
を使用できます。
主題についての私の考えは単純です。アップロードされたすべての画像は悪です。
また、悪意のあるコードが含まれている可能性があるだけでなく、特にメタタグが原因です。 Webを閲覧して、隠されたメタタグを使用して保護された画像を見つけ、著作権で遊ぶクローラーについて知っています。おそらく少し偏執狂かもしれませんが、ユーザーがアップロードした画像は著作権の問題を制御できないため、真剣に考慮しています。
これらの問題を取り除くために、私は体系的にGdを使用してすべてのアップロードされた画像をpngに変換します。これには多くの利点があります。画像は最終的な悪意のあるコードやメタタグからクリーンであり、アップロードしたすべての画像に1つの形式しかないため、標準に合わせて画像サイズを調整できます...画像が有効かどうかすぐにわかります!画像を変換のために開くことができない場合(- imagecreatefromstring)を使用 これは画像に関係ありません形式)、私は画像を無効と見なします。
単純な実装は次のようになります。
function imageUploaded($source, $target)
{
// check for image size (see @DaveRandom's comment)
$size = getimagesize($source);
if ($size === false) {
throw new Exception("{$source}: Invalid image.");
}
if ($size[0] > 2000 || $size[1] > 2000) {
throw new Exception("{$source}: Too large.");
}
// loads it and convert it to png
$sourceImg = @imagecreatefromstring(@file_get_contents($source));
if ($sourceImg === false) {
throw new Exception("{$source}: Invalid image.");
}
$width = imagesx($sourceImg);
$height = imagesy($sourceImg);
$targetImg = imagecreatetruecolor($width, $height);
imagecopy($targetImg, $sourceImg, 0, 0, 0, 0, $width, $height);
imagedestroy($sourceImg);
imagepng($targetImg, $target);
imagedestroy($targetImg);
}
テストするには:
header('Content-type: image/png');
imageUploaded('http://www.dogsdata.com/wp-content/uploads/2012/03/Companion-Yellow-dog.jpg', 'php://output');
これはあなたの質問に正確に答えるものではありません。これは受け入れられた答えと同じ種類のハッキングですが、少なくとも:-)を使用する私の理由を説明します。
Uploadifyが本当にMIMEタイプを変更する場合-私はそれをバグと見なします。これは、開発者がPHPでMIMEタイプベースの関数を操作するのを妨げるため、まったく意味がありません。
これは、ファイルの最初の6バイトに基づいてMIMEタイプを返す小さなヘルパー関数です。
/**
* Returns the image mime-type based on the first 6 bytes of a file
* It defaults to "application/octet-stream".
* It returns false, if problem with file or empty file.
*
* @param string $file
* @return string Mime-Type
*/
function isImage($file)
{
$fh = fopen($file,'rb');
if ($fh) {
$bytes = fread($fh, 6); // read 6 bytes
fclose($fh); // close file
if ($bytes === false) { // bytes there?
return false;
}
// ok, bytes there, lets compare....
if (substr($bytes,0,3) == "\xff\xd8\xff") {
return 'image/jpeg';
}
if ($bytes == "\x89PNG\x0d\x0a") {
return 'image/png';
}
if ($bytes == "GIF87a" or $bytes == "GIF89a") {
return 'image/gif';
}
return 'application/octet-stream';
}
return false;
}
exif_imagetype を使用して、画像の実際のタイプを取得してみてください。ファイルが小さすぎる場合はエラーがスローされ、ファイルが見つからない場合はfalseが返されます
ファイルの最初の数バイトで マジックナンバー を確認して、画像形式を確認できます。
finfo_file でファイルに問い合わせることはできませんか?
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename); //should contain mime-type
finfo_close($finfo);
この回答はテストされていませんが、Uploadifyフォーラムの このフォーラムディスカッション に基づいています。
私はまた、finfoが "ファイル内の特定の位置で特定のマジックバイトシーケンスを探すことにより、ファイルのコンテンツタイプとエンコーディングを推測してみてください" であることを指摘します。 Uploadifyは誤ったMIMEタイプを指定していますが。