我想我設法想出一個解決方案。這是一個應該檢測不完整圖像文件的代碼。 僅支持PNG和JPEG格式,因爲我目前不需要其他格式支持。它通過檢查JPEG的SOI和EOI以及PNG的IDHR和IEND來工作。
您可以將兩個參數傳遞給此函數 - 文件名以及JPEG本身是否有更多的JPEG。
如果在調用函數時指定了$jpeg_in_jpeg
,則會執行較慢的腳本來檢查SOI計數是否等於EOI計數,因此文件是整個文件。雖然這隻會在JPEG內部EOI文件結束時才需要,但是您需要非常不幸纔會發生這種情況。
更新:我意識到解析所有的數據爲字節和到一個數組,然後比較值是極其緩慢的。 1.145 MB的JPEG圖像將在26秒內被檢查!但現在我把它改爲preg_match_all()
,現在它快了800倍。有問題的數字是(以秒爲單位):
26,64180707931471(舊方法)/ 0.032716035842896(新方法)= 814,3348175570528(倍數更快)。
如果您真的需要速度,並且不認爲您會因爲文件以內部JPEG的EOI結束而感到非常不幸,請使用更快速的方法,方法是不指定$jpeg_in_jpeg
。與新的$jpeg_in_jpeg
方法相比,速度將增加約2,6倍。的數字是(秒):
0.032716035842896($jpeg_in_jpeg = true
)/ 0.012523889541626($jpeg_in_jpeg
未指定)= 2,612290353907259(倍的速度)
記住這是所有測試在樹莓裨乙模型。在普通服務器上,該函數的執行時間應該縮短很多。
function isImageComplete($file_name, $jpeg_in_jpeg = null){
$image_type = @exif_imagetype($file_name);
if($image_type)
$data = file_get_contents($file_name);
if($image_type == IMAGETYPE_JPEG){
if($jpeg_in_jpeg){
#Note: Some JPEG images have even more JPEGs inside of them (have multiple SOI and EOI). This check is slow, though eliminates the very small chance of detecting thumbnail's EOI as the file's ending.
$soi = chr(255).chr(216);
$eoi = chr(255).chr(217);
$results = preg_match_all("/$soi|$eoi/", $data, $out, PREG_PATTERN_ORDER);
$soi_count = 0;
$eoi_count = 0;
foreach($out[0] as $o)
if(ord($o[0]).ord($o[1]) == "255216")
$soi_count++;
elseif(ord($o[0]).ord($o[1]) == "255217")
$eoi_count++;
if($soi_count == $eoi_count && $soi_count > 1)
return 1;
else
return 0;
}
else{
$soi = substr($data, 0, 2);
$eoi = substr($data, -2);
$pair_count = 0;
if(ord($soi[0]).ord($soi[1]) == "255216")
$pair_count++;
if(ord($eoi[0]).ord($eoi[1]) == "255217")
$pair_count++;
if($pair_count == 2)
return 1;
else
return 0;
}
}
elseif($image_type == IMAGETYPE_PNG) {
$a_idhr = array();
$a_iend = array();
$idhr = substr($data, 0, 8);
$iend = substr($data, -12);
foreach(str_split($idhr) as $char){
array_push($a_idhr, ord($char));
}
foreach(str_split($iend) as $char){
array_push($a_iend, ord($char));
}
if(implode('', $a_idhr) == '13780787113102610' && implode('', $a_iend) == '0000736978681746696130')
return 1;
else
return 0;
}
else{
return -1; #File format not supported by the function.
}
}
雖然我RPI玩弄,我發現我有JPEG文件內的另一個JPEG圖像,雖然exif_thumbnail()
沒有返回任何東西。我想你可以試着檢查一下exif_thumbnail()
是否會返回一些內容,然後再使用較慢的$jpeg_in_jpeg
。但是,正如我發現的,它不會返回內部的JPEG。這可能是因爲它沒有被當作縮略圖,而是被當作別的東西。請記住,這是我第一次鑽研圖像文件格式,所以我知道的很少。
我不知道代碼的哪一部分決定是否下載文件,但您可以嘗試檢查文件大小以及修改時間。這至少應該抓住部分寫道。 –
我只是使用if(!file_exists($ path))。現在通過檢查文件大小是什麼意思?是否可以在不完全下載的情況下知道外部圖像的文件大小?我有這樣的想法,即運行多個測試來計算文件大小,通過寬度,高度和位圖來提供寬度,高度和位圖。但是這也可能會導致錯誤的結果,因爲我不知道確切的位深度。或者我可以用相同的格式計算所有圖像的平均比特深度,然後將其與其他圖像進行比較,看看它們有多少不同。但不同的壓縮壽命。 – Aistis
你可以做一個頭部請求來獲取實際的文件大小,並使用php文件大小在本地進行檢查。這也可以爲您提供修改日期。 –