Java流式传输大.xlsx文件到浏览器时出现sharedStrings.xml保存异常求助
我之前帮朋友排查过几乎一模一样的问题——就是用Java生成大xlsx文件,流式传给浏览器时,只有大文件会报/xl/sharedStrings.xml 部分无法通过编组器保存的错误,小文件完全正常。核心原因其实很明确:默认的XSSF模式会把整个文档(包括所有共享字符串)都加载到内存里,大文件直接把内存撑爆,导致XML编组失败。
下面给你几个亲测有效的解决方案,按优先级排序:
1. 立刻切换到SXSSF流式处理API
这是最根本的解决办法,POI专门为大文件设计了SXSSF,它会把超出内存阈值的数据写到磁盘临时文件,不会让内存飙升。关键是要正确配置它:
// 创建SXSSFWorkbook,设置内存中保留100行数据,超过的自动写到临时文件 SXSSFWorkbook workbook = new SXSSFWorkbook(100); // 确保开启共享字符串表(默认是开启的,但大文件下建议显式设置) workbook.setUseSharedStringsTable(true); // 后续创建工作表、写入数据的逻辑和XSSF基本一致 Sheet sheet = workbook.createSheet("超大数据集"); // 这里写你的数据循环逻辑,哪怕几十万行都没问题 // 输出到浏览器的部分也要注意 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=large_data.xlsx"); OutputStream out = response.getOutputStream(); workbook.write(out); out.flush(); // 一定要调用dispose清理临时文件,不然磁盘会被占满 workbook.dispose();
2. 检查服务器的流超时配置
大文件下载耗时久,很可能服务器端提前把连接断了,导致写流中断引发错误。比如Tomcat的话,你需要调整这两个参数:
connectionTimeout:连接超时时间,默认20秒,改成300秒(5分钟)足够应付大部分大文件keepAliveTimeout:长连接超时时间,同样调大一些
如果是Spring Boot项目,可以在application.properties里直接配置:
server.tomcat.connection-timeout=300000 server.tomcat.keep-alive-timeout=300000
3. 升级POI到最新稳定版
有些旧版本的POI在处理超大共享字符串表时存在bug,比如4.0.0之前的版本,升级到4.1.2或者5.x的稳定版,很多这类问题会直接消失。
4. 万不得已的临时方案(不推荐)
如果因为某些原因不能用SXSSF,只能用XSSF的话:
- 手动调整JVM堆内存,比如启动时加
-Xmx4g(根据服务器配置调整),但这只是治标,文件再大还是会崩 - 尽量减少重复文本的使用,降低共享字符串表的大小
最后提醒下:用SXSSF的时候,千万别忘了调用dispose(),不然每次生成大文件都会留下临时文件,时间长了磁盘会被塞满。
内容的提问来源于stack exchange,提问作者Siddam
相关产品推荐
相关产品推荐

