接口写完,前端点导出,浏览器下下来的文件名是一串乱码,后缀也没有,双击直接弹选择打开方式。十有八九是响应头没设对,或者把文件流塞进了统一返回体。
响应头三件事
第一,Content-Type 设成 xlsx 对应的 MIME,值是 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,用字符串常量写进去就行。第二,Content-Disposition 用 attachment 加 filename,中文名要做 URL 编码,否则浏览器会丢掉文件名。第三,写完把输出流 flush 掉再关,中间别再往 body 里写东西。
全局异常处理器要留意,导出过程中抛了异常,它往往往同一个响应里写一段 JSON,文件就带着半截报错内容,打不开。
写表用哪个库
老项目多是 Apache POI。几万行以内用 XSSFWorkbook 没问题,再往上换 SXSSFWorkbook,它把行刷到临时文件,内存占得少:
SXSSFWorkbook wb = new SXSSFWorkbook(500); Sheet sheet = wb.createSheet();想少写样板代码,EasyExcel 更顺手,给个实体类就有表头,直接往响应流里写:
EasyExcel.write(response.getOutputStream(), Order.class).sheet().doWrite(list);流直接用响应里的 outputStream,别再先存本地文件再读出来,白折腾一次磁盘。
实际会踩的四个点
- 查询没分页,一次拉全表,堆内存先炸。
- 方法上挂着事务,导出跑两分钟,连接一直占着,跑久了被超时回收。
- 金额用 double 写进单元格,出现一长串小数。
- 文件名里有斜杠,头信息被浏览器截断,项目里统一过滤掉。
判断:小表用 POI,上万行用 SXSSF 或 EasyExcel,导出接口单独开一个,别和列表接口共用一个方法。