我想我设法想出一个解决方案。这是一个应该检测不完整图像文件的代码。 仅支持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文件大小在本地进行检查。这也可以为您提供修改日期。 –