项目场景:
Java读取静态目录文件 复制并导出
一个简单的、经典的、流导出,前端用window.open(url)下载,这里window.open 疑似不携带token,所以导出带当前登录人信息的不适用,并且要在shiroConfig中添加好白名单。
问题描述
在下载完成后打开总是文件损坏
@RequestMapping("/exportExcel")
public void exportExcel(HttpServletResponse response) {
// 读取静态文件目录
Resource classPathResource = new ClassPathResource("static/终端数据导入模板.xlsx");
InputStream inputStream = null;
try {
//写入流中
inputStream = classPathResource.getInputStream();
//获取响应流
OutputStream outputStream = response.getOutputStream();
// 写入响应流中
byte[] buffer = new byte[inputStream.available()];
// 流中写入的是字节
int bytesRead;
// 读入流写出流
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
//设置响应头和contentType
response.setHeader("Content-Disposition", "attachment; filename=终端数据导入模板.xlsx");
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
// 结束关流,不关流会导致文件损坏
inputStream.close();
outputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
原因分析:
- 流没有正确关闭。(打断点测试了一下,不关流不输出文件)
- 流没有刷新。(加了outputStream.flush() 纯纯互联网大骗子)
- 源文件就是个损坏的。 (文件是好的,人不行怪路不平…)
解决方案:
文件损坏主要是从一下几个方面开始排查:
确保正确设置响应头: 确保在写入响应流之前正确设置了响应头信息,特别是 Content-Disposition 和 Content-Type。
适当设置文件编码和类型: 确保设置了正确的编码和文件类型(MIME 类型),如 application/vnd.ms-excel;charset=UTF-8 用于 Excel 文件。
使用专门的库生成 Excel 文件: 考虑使用 Apache POI 等专门用于生成 Excel 文件的库,以确保生成的文件格式正确并且与 Excel 兼容。
避免在 Excel 文件中包含 HTML 内容: 如果在生成 Excel 文件时包含了 HTML 内容,可能会导致文件损坏。确保生成的内容是纯文本或符合 Excel 格式规范的内容。
关闭流操作: 确保在最终将文件写入响应流后,关闭相关的输入流和输出流,避免资源泄漏。
我这里的原因貌似是文件的类型不太兼容。