文章目录
一次解决Easypoi导出Excel文件打开乱码问题的过程
前言
项目中使用Easypoi来导出Excel,上线后是正常的,过了段时间,测试反馈导出的Excel文件打开乱码,打开Excel文件时提示“文件格式和扩展名不匹配…文件可能已损坏或不安全”。
导出Excel过程:
-
前端发起一个
POST
请求; -
后端响应请求,在导出Excel文件时,在HTTP头部设置
Content-Type
为application/vnd.ms-excel
,并且设置字符集为UTF-8
, 并通过设置Content-Disposition
为attachment;filename=...
来让浏览器下载附件。
后端代码示例:
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.ms-excel; charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(response.getOutputStream());
解决问题过程
排查最近的变更
最近做了什么代码变更?
- 排查了后端代码,没有改动过导出部分的代码;
- 前端也反馈,没有改动过导出部分的代码。
最近做了什么配置变更?
团队反馈最近没有做过什么“可疑”的变更。
定位问题
前端问题还是后端问题?
因为通过Postman的Send and download测试,导出的Excel也有同样的问题。
因此可以排除是前端问题。
Maven依赖冲突问题?
团队反馈最近在parent项目中的pom.xml有引入xxl-tools
,而xxl-tools
也有Excel导出功能,会不会和Easypoi的导出功能有冲突?
但是这个项目中并没有xxl-tools
依赖,用IDEA查看Maven依赖图也证实了这一点。
并且parent项目中是以dependencyManagement
来引入xxl-tools
,也就是只有子项目明确引入了xxl-tools
,才会有xxl-tools
依赖。
因此可以排除是Maven依赖冲突问题。
Linux环境问题?
运行echo $LANG
和locale
命令比较了几台测试服务器的Linux环境配置,没有发现异常。
在项目中编写测试代码,导出文件时直接生成Excel文件并保存在服务器上,再手工从服务器上下载Excel文件到本地打开,没有问题。
因此可以排除是Linux环境问题。
Easypoi问题?
项目中引入的Easypoi已经指定了特定版本,并且之前导出是正常的,Easypoi的嫌疑不大。
稳妥起见,改成用原始的Apache Poi来导出,一样有问题。
因此可以排除是Easypoi库的问题。
网关问题?
前端发起请求时,会先通过网关,再由网关转发到后端来处理,所以网关也有嫌疑。
测试不经过网关,直接调用项目的导出Excel接口,果然没有问题。
网关是我们基于Spring Cloud Gateway定制的,里面定义了几个拦截器(filter)来对HTTP request和HTTP response做了日志记录、格式转换和异常处理等。
查看网关代码,最近并没有可疑的改动。
但是看到一个记录日志的拦截器代码中在某些情况时会对HTTP response重写,重点怀疑。
通过开关,关闭该拦截器后,测试正常。
终于抓到真凶了。
虽然该拦截器代码最近并没有改动过,但是之前环境上该拦截器没有开启,所以导出是正常的,后来不知道什么时候开启了这个拦截器,就影响到导出功能了。
解决问题
修改有问题的拦截器,根据接口URL来判断,对导出文件时直接跳过该拦截器。
测试通过。
小结
本文通过一次排查导出Excel文件问题的过程,描述了在导出文件过程的前端、网关和后端服务(接口、库、服务器)的各个阶段都可能存在的故障点,提供了排查类似问题的参考。