在PHP中,为什么imagecreatefromjpeg的“不是jpeg文件”错误已更改为致命错误?

9

我有一份旧的代码,试图加载一张图片文件。由于它不知道它的类型是什么,所以代码尝试了所有的类型:

$res = @imagecreatefromjpeg($sourceName);
if ( $res === false)
    $res = @imagecreatefromgif($sourceName);
if ( $res === false)
    $res = @imagecreatefrompng($sourceName);
if ( $res === false) {
    $err[] = 'Cannot load file as JPEG, GIF or PNG!';

长期以来,这段代码一直能够完美运行,但是在最近的服务器迁移后,当使用PNG文件时(JPEG文件正常工作),它停止了工作。调查发现,第一行代码就产生了致命错误:
``` Fatal error: imagecreatefromjpeg(): gd-jpeg: JPEG library reports unrecoverable error: Not a JPEG file: starts with 0x89 0x50 ```
由于该行代码有错误抑制运算符,因此脚本仅停止执行,并返回带有空响应的HTTP 200。
我不明白的是...什么...怎么...为什么...从何时开始...嗯?
即使是官方文档也说,这些函数在无法加载文件时会返回FALSE,并且在那里也显示了带有@运算符的结构。我在网上找不到任何关于“不是JPEG文件”的致命错误的信息。无论在哪里提到它,它都是一个警告,就像一直以来一样。为什么我现在会得到致命错误?
我的PHP版本是5.6.30,GD已安装并配置正确。

你看过这个这个吗?它们或许值得一看(处理有问题的JPEG图片)。 - Darren
1
@Darren - 这两个链接都提到了在失败时出现的警告。这是可以被抑制和忽略的警告。但我得到的是一个致命错误。此外,我已经声明这不是一个有缺陷的jpeg文件 - 它是一个png文件,我期望这个函数会失败 - 只是不会致命。 - Vilx-
2个回答

6

我想我可以回答自己的问题了。这是一个已知的 bug。请参阅 PHP bugs #73514#73479。实际上,这个 bug 在 libgd 中,并且已经在那里报告过了。去年11月份就修复了此问题,但仍未发布新版本。所以,嗯...没有办法。我将尝试使用getimagesize()来先确定类型,然后再使用适当的函数。虽然这对于真正损坏的文件无济于事,但总比没有好。


请检查图像的MIME类型是否正确。如果不同,则无法正常工作。我曾经遇到过类似的问题,发现我的图像扩展名是.jpg,但是在图像的MIME类型中却得到了image/png,这是错误的。因此,我通过设置正确的图像MIME类型来解决了这个问题。 - Bhatt Akshay
该文件是由用户上传的,因此MIME类型标头不可靠 - 而且我甚至不知道它们是否可以从PHP开始访问。 - Vilx-
在上传图像到服务器时,您还可以设置其MIME类型。 - Bhatt Akshay
@BhattAkshay - 那么,请再告诉我,我应该在哪里查找图像的 MIME 类型? - Vilx-
getimagesize('文件路径或文件URL'); 它将给出文件的MIME类型。 - Bhatt Akshay
显示剩余6条评论

0
问题在于您的文件扩展名有误,根据前几个字节,它实际上是PNG格式,而不是JPG。我的解决方案是检测前几个字节并将文件重命名为PNG格式:
$firstBytes = bin2hex(file_get_contents($tmp_name,false,null,0,2));
if ($firstBytes==8950) $_FILES['file']['name'].= '.png';

文件扩展名对于imagecreatefromXXX()函数来说是无关紧要的。是的,我想要做到这一点——根据文件内容检测文件类型,并使用相应的函数打开它。查看前几个字节是正确的,但并不总是非常简单。例如,JPEG有4种不同的可能头。这就是为什么我不想自己去做,而是使用一些其他知道所有细节的库。例如,getimagesize()函数可以实现这一点。 - Vilx-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接