问题场景
新项目上需要用到页面上Excel导出下载,于是把老项目中用了很久的一个Excel工具类拿了过来,因为老项目导出的是 xls文件,新项目需要导出 xlsx,就对着改了下,改完之后导出文件,发现会弹出提示
点击是之后,文件能正常查看,文件内容也没问题。
问题原因
开始以为是新旧Excel类型的样式不兼容,最后检查发现是导出的文件流处理有问题。
工具类中处理文件用的是字节流写入,其实不该这么做,特别是导出文件多半是有中文的情况,但是在xls文件中并没有产生问题
public static void ioWriteForSheets(HttpServletRequest request, XSSFWorkbook workbook, HttpServletResponse response, String excelName) {
try {
String agent = request.getHeader("USER-AGENT");
boolean isIe = null != agent && agent.contains("MSIE") || null != agent
&& agent.contains("Trident") || null != agent && agent.contains("Edge");
if (isIe) {
// ie
String fileName = java.net.URLEncoder.encode(excelName, "UTF8");
response.addHeader("Content-Disposition", "attachment;filename="
+ fileName + ".xlsx");
} else if (null != agent && agent.contains("Mozilla")) {
// 火狐,chrome等
String fileName = new String(excelName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
response.addHeader("Content-Disposition", "attachment;filename="
+ fileName + ".xlsx");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
OutputStream os = response.getOutputStream();
ByteArrayInputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
byte[] b = new byte[1024];
while ((inputStream.read(b)) > 0) {
os.write(b);
}
inputStream.close();
os.flush();
os.close();
} catch (IOException e) {
exceptionHandle(e);
}
}
其实不该这么绕,可以直接将workbook 的流写入response中,并且解决了问题 修改之后的代码:
public static void ioWriteForSheets(HttpServletRequest request, XSSFWorkbook workbook, HttpServletResponse response, String excelName) {
try {
String agent = request.getHeader("USER-AGENT");
boolean isIe = null != agent && agent.contains("MSIE") || null != agent
&& agent.contains("Trident") || null != agent && agent.contains("Edge");
if (isIe) {
// ie
String fileName = java.net.URLEncoder.encode(excelName, "UTF8");
response.addHeader("Content-Disposition", "attachment;filename="
+ fileName + ".xlsx");
} else if (null != agent && agent.contains("Mozilla")) {
// 火狐,chrome等
String fileName = new String(excelName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
response.addHeader("Content-Disposition", "attachment;filename="
+ fileName + ".xlsx");
}
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
// 直接写入response的输出流
workbook.write(response.getOutputStream());
} catch (IOException e) {
exceptionHandle(e);
}
}