解决ImageIO无法读取部分JPEG格式图片问题

发布于:2024-10-16 ⋅ 阅读:(13) ⋅ 点赞:(0)

解决ImageIO无法读取部分JPEG格式图片问题

问题描述

  我最近对在线聊天功能进行了一些内存优化,结果在回归测试时,突然发现有张图片总是发送失败。测试同事把问题转到我这儿来看,我仔细检查了一下,发现是上传文件的接口报错,说文件格式不符合要求。乍一看这问题似乎很简单,文件格式限制而已。我心想:JPEG 格式不应该是允许的么?然而,当我右键查看文件属性,心里瞬间有种不好的预感——这张图片确实是 JPEG 格式的,而系统明明允许上传 JPEG 类型的文件。这就变得有趣了。

问题排查

  首先,我查看了测试环境的日志,却没有任何有用的线索。然后打开上传服务的代码,检查文件处理的逻辑,看起来一切正常,没有明显问题。既然看不出来问题,那就只能踏踏实实地 debug 了。

  服务启动后,我用另一张 JPEG 图片测试了一下,结果上传成功了。这让我怀疑测试环境的代码和我们本地的版本有差异。于是,我再次使用之前总是上传失败的图片,测试后同样报了和测试环境一样的错误。我将断点打在文件校验的部分,逐行调试,结果发现所有的校验步骤都通过了!看来问题不在文件类型校验上。继续深入调试,发现流程走到了文件为空的逻辑,然后直接返回了“不允许上传该文件类型”的错误。这让我摸不着头脑——文件明明有大小,而且后端也没有报错,怎么会读取不到文件内容?

接着,我看了一下获取图片内容的代码:

BufferedImage image  = ImageIO.read(fileData.getInputStream());

看起来平平无奇,但是这个image 对象返回来的确实是null

问题原因

  经过深入分析,终于找到了问题的根源:ImageIO.read() 方法在 Java 中并不支持 .webp 格式图片的读取。这是因为 ImageIO 类依赖的 SPI(Service Provider Interface)机制,只为常见的图片格式(如 PNGJPEGGIF 等)注册了相应的读取器,但并没有对较新的 WEBP 格式提供内置支持。

  当我们尝试用记事本打开那张图片时,发现它的确是 WEBP 格式,而不是我们最初以为的 JPEG。这就解释了为什么系统上传失败——ImageIO.read() 方法无法处理 WEBP 格式的文件,导致图片无法被正确读取,进而触发了文件格式不符合要求的错误。

有问题的JEPG图片数据:
在这里插入图片描述

正常的JEPG图片数据:
在这里插入图片描述

问题修复

解决这个问题也非常简单,直接在pom文件引入如下组件:

 <dependency>
   <groupId>org.sejda.imageio</groupId>
   <artifactId>webp-imageio</artifactId>
   <version>0.1.6</version>
 </dependency>

然后就可以了!!!