問題場景
新項目上需要用到頁面上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);
}
}