我想檢查一個上傳的文件是否是一個圖像文件(如PNG,JPG,JPEG,GIF,BMP)或其他文件。問題是我正在使用Uploadify上傳文件,這些文件會更改MIME類型,並給出「文本/八進制」或其他類型的MIME類型,無論您上傳的是哪種文件類型。如何檢查上傳的文件是否爲沒有MIME類型的圖像?
有沒有辦法檢查上傳的文件是否是除了使用PHP檢查文件擴展名之外的圖像?
我想檢查一個上傳的文件是否是一個圖像文件(如PNG,JPG,JPEG,GIF,BMP)或其他文件。問題是我正在使用Uploadify上傳文件,這些文件會更改MIME類型,並給出「文本/八進制」或其他類型的MIME類型,無論您上傳的是哪種文件類型。如何檢查上傳的文件是否爲沒有MIME類型的圖像?
有沒有辦法檢查上傳的文件是否是除了使用PHP檢查文件擴展名之外的圖像?
您可以使用getimagesize()
,它在非圖像上返回零大小。
您可以檢查magic number文件的前幾個字節來確定圖像格式。
嘗試更多的信息。如果文件太小就會拋出錯誤,如果找不到則返回錯誤
我對這個主題的想法很簡單:所有上傳的圖片都是邪惡的。
而且不僅因爲它們可以包含惡意代碼,而且特別是因爲元標記。我瞭解使用隱藏元標記瀏覽網頁以找到一些受保護圖像的抓取工具,然後播放其版權。也許有點偏執狂,但由於用戶上傳的圖片在版權問題上失控,我謹慎考慮。
爲了擺脫這些問題,我使用gd系統地將所有上傳的圖像轉換爲png。這有很多優點:從最終的惡意代碼和元標記,圖像是乾淨的,我只有一個格式的所有上傳的圖像,我可以調整圖像大小,以符合我的標準,並... 我立即知道是否圖像是否有效!如果圖像無法打開進行轉換(使用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');
這並不完全回答你的問題,因爲這是同一種黑客比接受的答案的,但我給你我的理由使用它,至少:-)
我完全同意@Alain Tiemblo「我使用gd系統地將所有上傳的圖片轉換爲png」。這是安全性的一種方式。 – PauloASilva
事實上,我的一位同事指出,如果你允許動畫GIF,這是行不通的。真正。 –
我同意你但是...每個人都知道GIF可以被利用([示例])(http://www.phpclasses.org/blog/post/67-PHP-security-exploit-with-GIF-images.html ))。如果您需要支持GIF,也許您必須投入一些時間和精力來過濾/清除格式。 – PauloASilva
如果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;
}
是不是可以用finfo_file詢問文件?
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename); //should contain mime-type
finfo_close($finfo);
這個答案是未經測試,而是基於this forum discussion的Uploadify論壇。
我還要指出,finfo應該是"try to guess the content type and encoding of a file by looking for certain magic byte sequences at specific positions within the file",所以在我看來,即使Uploadify指定了錯誤的MIME類型,它也應該可以工作。
據我所知,這實際上是完成這件事的可接受的手段。如果它們存在,我會對更好的方法有興趣。 –
文檔說它返回一個包含7個元素的數組,我需要檢查它的圖像是否需要檢查哪個元素? –
零和一個寬度和高度。 –