WEBP格式的图片导致ImageIO.read方法return null
1. 问题背景 最近开发一个图片服务,主要是维护项目图片,支持JPG、BMP、PNG、JPEG等常规格式。开发的时候没问题,但是上到生产的时候,客户在维护图片的时候,发现有的JPG格式的图片能上传,有的不能。 拿到正常上传和不能上传的图片,对比发现,不能上传的图片,在windows上根本无法打开,图片如下(用chrome打开可以看见,右键另存图片,或者 点击这里下载): 但是奇怪的是,该图片可以在chrome浏览器显示,也可以在安卓APP上显示,但是其他浏览器和iOS无法正常显示。 2. 问题分析 首先debug代码,发现图片都会使用ImageIO来读取,以便获取图片宽高从而进行等比例压缩,代码如下: BufferedImage bi = ImageIO.read(inputStream); Map rtnMap = new HashMap(); if (bi == null) { rtnMap.put("status", "1"); //上传不成功 rtnMap.put("msg", "该图片本身不是图片格式"); return rtnMap; } 非正常图片,上边的bi会返回null,而不会抛出任何异常信息。 首先怀疑图片是损坏的,因为windows上根本无法打开,显示如下: 但是该图片可以在chrome上正常显示,这表明图片不会是损坏了,应该是跟平台有关,那么会不会是图片格式根本不是JPG,仅仅后缀显示为JPG呢? 然后我用记事本打开正常的和非正常的图片文件进行比对,想获取一些有用的信息,结果发现: 非正常JPG图片 正常JPG图片 如上所示,正常JPG里边,显示格式为JFIF,而非正常图片显示为WEBPVP8,明显不同。看来,不能正常上传的图片是平台不支持的图片格式,到底WEBPVP8是什么格式? 3. WEBP格式 通过谷歌搜索,查询半天发现,这种格式名为WEBP,由谷歌开发,官方地址(记得翻墙): https://developers.google.com/speed/webp/?hl=zh-CN,也是图片格式的一种, 百度百科原文如下: WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。Facebook Ebay等知名网站已经开始测试并使用WebP格式。 但WebP是一种有损压缩。相较编码JPEG文件,编码同样质量的WebP文件需要占用更多的计算资源。桌面版Chrome可打开WebP格式。 恍然大悟,原来是一种新型图片格式,很明显windows和iOS还不支持,但是谷歌旗下产品可以支持,这就解释了为什么chrome、安卓能够打开。 在JAVA中,还不支持这种格式,可以用如下代码检查当前支持的图片格式: String[] ss = ImageIO.getReaderFormatNames(); System.out.println(Arrays.asList(ss)); 返回结果:[JPG, jpg, bmp, BMP, gif, GIF, WBMP, png, PNG, jpeg, wbmp, JPEG] 在查找问题时,我还尝试使用twelvemonkeys扩展包来扩展所支持的图片类型: <dependency> <group>com.twelvemonkeys.imageio</group> <artifact>imageio-jpeg</artifact> <version>3.3.2</version> </dependency> <dependency> <group>com.twelvemonkeys.imageio</group> <artifact>imageio-tiff</artifact> <version>3.3.2</version> </dependency> <dependency> <group>com.twelvemonkeys.imageio</group> <artifact>imageio-pnm</artifact> <version>3.3.2</version> </dependency> ...