【错误记录】导入xlsx文件 解析文件内容时出错java.io.IOException: Zip bomb detected 错误原因及解释

本文探讨了后端接口在导入Excel文件时遇到的压缩炸弹检测问题,解释了ZipBomb概念,指出xlsx本质上是压缩文件,以及如何设置压缩率避免检测。解决办法包括设置低压缩率或关闭判断,同时提供了相关参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导入文件时,报错信息:
在这里插入图片描述

事件起因:

在编写一个后端接口,导入文件的功能的时候,一旦导入一个excel文件 后端就会报这个错误,然后这个接口也就不能去具体执行相应的业务功能

在网络上看了许多的解决办法,但是很多都没有对其原因进行解释,在找完相关资料后来记录一下,这个bug的原因
希望在发现问题解决问题的过程中,能够做到:知其然,知其所以然

ZipBomb是什么?

首先要明白这是一个什么东西,直译就是 “压缩炸弹” 在导入文件时会对压缩文件进行识别,然后判断它的压缩率,至于为什么要去判断这个,大家可以去搜索一下这个ZipBomb是什么(最经典的就是一个42kb的压缩包其实是一个4.5Pb的炸弹,这会直接占满你的电脑磁盘空间)
1PB = 1024TB
1TB = 1024GB
1GB = 1024MB
1MB = 1024KB
1KB = 1024B

在写程序(后端接口上传文件时),检查拉链炸弹(即包含大量高度可压缩数据(00000000000000000 …)的zip文件) 是从安全的角度去考虑,避免上传的文件占满服务器的磁盘空间

关于压缩率的设置:
ZipSecureFile.setMinInflateRatio(-1.0d);

ZipSecureFile.setMinInflateRatio(0.009);

ZipSecureFile.setMinInflateRatio(0);

括号中的数字所代表的意思是:压缩率, 是compressBytes / uncompressBytes 的比率 也就是 “压缩后大小 / 压缩前大小” 如果这个比率是0.01d 说明压缩后文件比压缩前文件小100倍而没有信息丢失,换句话说,压缩文件仅在文件大小的1%中存储相同的信息 压缩率是一个分数,分子(压缩)必定小于或等于分母(未压缩)所以取值范围为 (0,1]
若不进行set设置压缩率,压缩率默认为 1% (= 0.01d),即当任何给定的读取包部分的压缩率优于(压缩效果更好,低于默认值) 1% 时,解析将失败,指示 Zip-Bomb。

明白了 ZipBomb 是什么后,有不少小伙伴就有了一个疑问:

疑问:我明明导入的是一个excel 都不是压缩文件 为什么会进行压缩炸弹的检测呢?

这个还得根据导入的文件类型来说:
我们常使用的excel文件其实有两种后缀名(两种文件类型),也就是".xls"和".xlsx"
这两种文件格式还是存在着细微区别的
xls:该文件格式是excel2007之前版本的默认格式
xlsx:xlsx是excel 2007之后的版本使用的默认格式,包括2007的版本,xlsx是用新的基于XML的压缩文件格式取代了xls默认文件格式

xlsx在本质上还是一个zip文件,将xlsx(或xlsm)文件扩展名改为zip,用解压软件解压,可以看到OOXMl格式的文件内容
将我的xlsx文件后缀名变为zip用解压软件打开的样子:
在这里插入图片描述

已测试导入xls文件和xlsx文件时(同一个文件导出格式分别为xls和xlsx两份) (从下图就可以看出这两种文件的有压缩和没有压缩在大小上的区别 )
在这里插入图片描述

调用接口测试两个文件的导入情况,报错信息不同:
xls文件:
在这里插入图片描述
xlsx文件的报错就是上面第一张图那样的

解决办法

办法就是在读取文件前设置压缩率为 -1.0d 这样的压缩率永远无法达到, 所以不会有比这个比率更优(低)的比率,这样其实相当于关闭了判断文件的压缩率,不过这样笔者觉得可能会引发安全问题,但我们平常的一些小系统开发,又不需要考虑这样的安全问题(又没有任何的商业价值,不会谁吃饱了撑的闲得没事真的来搞我的服务器吧!嘶嘶嘶~~ 搞不好真有,但不是我这种小开发该考虑的问题)
ZipSecureFile.setMinInflateRatio(-1.0d);

参考资料

ZipSecureFile类的说明:
https://poi.apache.org/apidocs/dev/org/apache/poi/openxml4j/util/ZipSecureFile.html

其他文章参考:
https://www.qedev.com/dev/151394.html

结束语

若是对你有所帮助的话,希望能获得你的 点赞、评论、收藏,这将是对我很大的鼓励!!! 这对我真的很重要!!!
蟹蟹٩(‘ω’)و

使用EasyExcel读取Excel模板并将其内容映射到Map中涉及以下几个步骤[^1]: 1. **添加依赖**: 如果还没有集成EasyExcel,需要先在项目中添加Spring Cloud Alibaba的Alibaba-EasyExcel依赖。 2. **配置读取器**: 创建一个`DataMapper`接口,用于定义从Excel单元格到Java Bean属性的映射关系: ```java public interface DataMapper { Map<String, Object> mapToEntity(Record record); } ``` 3. **创建实体类**: 基于模板创建一个Java Bean,例如`MyEntity`,每个字段对应Excel表的一列。 4. **设置读取策略**: 在`@ExcelReader`注解中指定模板名称、数据映射方式以及是否忽略空值: ```java @ExcelReader("template.xlsx", ignoreEmptyValue = true) public List<MyEntity> readFromTemplate(@Autowired DataMapper dataMapper) throws IOException { // 实际读取操作 } ``` 5. **解析模板到Map**: 在`readFromTemplate`方法内部,使用`dataMapper.mapToEntity(record)`将每一行`Record`转换为`Map`: ```java List<Record> records = ...; // 通过EasyExcel读取得到的数据记录列表 List<Map<String, Object>> maps = new ArrayList<>(); for (Record record : records) { maps.add(dataMapper.mapToEntity(record)); } ``` 6. **处理Map数据**: 获取到`Map`后,你可以根据实际需求进一步处理,如存储到数据库或其他地方。 如果读取遇到"Zip bomb detected!"错误[^2],可能是由于Excel文件大小超过了允许的压缩比限制,可以尝试减小文件大小,优化模板设计,或者调整EasyExcel的配置以适应大文件处理。具体解决方法可能包括分割大文件、调整压缩算法设置等。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿,葱来了-C is coming

老板大气

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值