JDK8-ImageIO读取gif历史遗留问题:ArrayIndexOutOfBoundsException: 4096

尊敬的家人朋友们,大家好!今天我们将探讨一些Java JDK 6~8版本中的gif读取的历史遗留问题,特别是那令人头疼的ArrayIndexOutOfBoundsException: 4096异常。在过去的几年里,许多Java开发者在处理GIF图像时可能遇到过这个问题,现在让我们一起来了解其中的原因和解决方案。

出问题的gif

JDK8-ImageIO读取gif历史遗留问题:ArrayIndexOutOfBoundsException: 4096_第1张图片

读取gif的代码

    @PostMapping("/file/gif/upload")
    public String uploadGif(HttpServletRequest request, @RequestParam("file") MultipartFile file) throws IOException {
         // 使用ImageIO读取gif获取上传图片的宽和高
        BufferedImage sourceImage = ImageIO.read(file.getInputStream());
        int sourceWidth = sourceImage.getWidth();// 上传图片的宽度
        int sourceHeight = sourceImage.getHeight();// 上传图片的高度
        log.info("上传图片的宽度:{},上传图片的高度:{}",sourceWidth,sourceHeight);
        //图片宽度和高度校验逻辑
        if(sourceWidth != 180 && sourceHeight != 180){
            return "兄弟,别乱传图片";
        }
        //图片上传fastdfs 并返回地址
        return dfsService.uploadFile(file);
    }

程序上传gif读取文件的代码BufferedImage sourceImage = ImageIO.read(file.getInputStream()); 会报ArrayIndexOutOfBoundsException: 4096异常,具体异常信息如下:

11:02:48.730 [http-nio-8180-exec-4] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - [log,175] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ArrayIndexOutOfBoundsException: 4096] with root cause
java.lang.ArrayIndexOutOfBoundsException: 4096
	at com.sun.imageio.plugins.gif.GIFImageReader.read(GIFImageReader.java:984)
	at javax.imageio.ImageIO.read(ImageIO.java:1448)
	at javax.imageio.ImageIO.read(ImageIO.java:1352)
	at cn.xj.file.controller.FileController.uploadGif(FileController.java:48)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)

异常原因

这个异常的根本原因在于GIF图像格式的特殊性。GIF(Graphics Interchange Format)是一种广泛使用的图像文件格式,它支持多帧动画和透明背景。然而,某些GIF图像使用了非标准的或不常见的压缩算法,或者包含了复杂的图像帧间数据。由于这些非标准特性,JDK 6~8中的GIFImageReader在解析这些特殊GIF图像时会遇到问题,从而导致数组索引越界的异常。

解决方案

方案一:重新压缩下图片(临时处理快捷、简便)

我们可以采用Photoshop重新保存下或者使用压缩工具压缩下gif就可以了

我们生产环境运营的时间较长了,修改代码验证代价较高,问题出现频率较低(3年出现了2次),所以我们采用的是这种处理方式

Photoshop重新保存之后可正常读取的gif

JDK8-ImageIO读取gif历史遗留问题:ArrayIndexOutOfBoundsException: 4096_第2张图片

我们可以比对下前后两张图片的属性,正常图片只是大小稍微增加了点

JDK8-ImageIO读取gif历史遗留问题:ArrayIndexOutOfBoundsException: 4096_第3张图片

方案二:使用更现代的图像处理库,更换gif读取的方式(一劳永逸)

我们可以在代码中使用别的gif处理库读取gif,示例代码使用的是hutool工具类GifDecoder读取的

    @PostMapping("/file/gif/upload1")
    public String uploadGif1(HttpServletRequest request, @RequestParam("file") MultipartFile file) throws IOException {
        // 使用hutool工具类GifDecoder读取gif获取上传图片的宽和高
        GifDecoder gifDecoder = new GifDecoder();
        gifDecoder.read(file.getInputStream());
        BufferedImage sourceImage = gifDecoder.getImage();
        int sourceWidth = sourceImage.getWidth();// 上传图片的宽度
        int sourceHeight = sourceImage.getHeight();// 上传图片的高度
        log.info("上传图片的宽度:{},上传图片的高度:{}",sourceWidth,sourceHeight);
        //图片宽度和高度校验逻辑
        if(sourceWidth != 180 || sourceHeight != 180){
            return "兄弟,别乱传gif";
        }
        //图片上传fastdfs 并返回地址
        return dfsService.uploadFile(file);
    }

方案三:升级jdk到9及以上(自己玩玩)

哪有企业随便升级这玩意啊,自己本地可以尝试下

结论

在JDK 6~8版本中,ArrayIndexOutOfBoundsException: 4096异常是一个常见而又让人烦恼的问题。然而,通过升级JDK版本、使用现代的图像处理库,以及对特定图像进行处理,我们可以有效地解决这个问题。同时,我们也应该注意检查图像文件的完整性,确保我们处理的是正确的、非损坏的图像文件。

希望本文对解决ArrayIndexOutOfBoundsException: 4096异常问题有所帮助。随着Java技术的不断发展,我们相信Java开发将变得更加轻松和愉快。感谢大家的阅读!如果您有任何问题或想法,请在评论中与我们分享。谢谢!

你可能感兴趣的:(java)