一、前言
Java開發中,常見的導入/導出插件是EasyPoi,簡單易學,功能強大。如果我們希望導出的檔案有複雜的樣式的時,使用EasyPoi的POJO類處理顯然就力不從心,是以就得使用EasyPoi模闆。由于項目部署環境和打包架構等問題,代碼中擷取EasyPoi模闆比較困難且容易導緻NPE。是以,可以使用FreeMarker模闆來做替換,該方法生成檔案時隻需要傳入文檔流即可。
FreeMarker模闆的制作,不在本篇部落格讨論。見本人另一篇部落格:
https://blog.csdn.net/qq_41057885/article/details/109686568
二、導出功能實作
1. Controller層實作
@GetMapping("aaa/bbb/ccc")
@ResponseBody
public void excelOut(Integer id) {
Map data = service.selectOneById(id);
// 擷取模闆檔案
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("static/excel/temp.ftl");
try {
// 生成導出文檔
File file = FreeMarkerUtils.createFile(inputStream, data);
// 此處可以填寫xls(excel)或者doc(word),主要看是什麼類型FreeMarker模闆
FreeMarkerUtils.downWord(response, file, "報表", "xls");
} catch (IOException e) {
e.printStackTrace();
}
}
2. FreeMarkerUtils工具類
public class FreeMarkerUtils {
/**
* 建立文檔
*/
public static File createFile(InputStream tempStream, Map dataMap) throws IOException {
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
String fileName = UUID.randomUUID().toString().replaceAll("-", "");
File file = new File(fileName);
try {
Template template = new Template(fileName, new InputStreamReader(tempStream), configuration);
Writer w = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
template.process(dataMap, w);
w.close();
} catch (Exception e) {
e.printStackTrace();
throw new IOException("建立文檔出錯");
}
return file;
}
/**
* 用戶端下載下傳文檔
*/
public static void downWord(HttpServletResponse response, File file, String fileName, String fileType) throws IOException {
// 設定浏覽器以下載下傳的方式處理該檔案的檔案名,支援中文
setFileDownloadHeader(response, fileName, "." + fileType);
InputStream fin = null;
ServletOutputStream out = null;
try {
// 調用工具類WordGenerator的createDoc方法生成Word文檔
fin = new FileInputStream(file);
out = response.getOutputStream();
byte[] buffer = new byte[1024];
int bytesToRead = -1;
// 通過循環将讀入的Word檔案的内容輸出到浏覽器中
while ((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} catch (Exception e) {
e.printStackTrace();
throw new IOException("下載下傳檔案出錯");
} finally {
if (fin != null) {
fin.close();
}
if (out != null) {
out.close();
}
if (file != null) {
// 删除臨時檔案
file.delete();
}
}
}
/**
* 設定讓浏覽器彈出下載下傳對話框的Header
*/
public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String fileType) {
try {
// 中文檔案名支援
String encodedfileName = new String(fileName.getBytes("GBK"), "ISO8859-1");
response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + fileType + "\"");
response.setCharacterEncoding("utf-8");
switch (fileType) {
case ".doc":
response.setContentType("application/msword");
break;
case ".docx":
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
break;
case ".xls":
response.setContentType("application/ms-excel");
break;
case ".xlsx":
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
break;
default:
break;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
3. 前端導出功能代碼
<!--HTML代碼-->
<button type="button" id="excelOutBtn" class="btn btn-sm bg-orange">
<i class="fa fa-cloud-upload fa-btn"></i> 導出
</button>
<!--JS-->
// 導出
$("#excelOutBtn").click(function () {
window.location.href = "${basePath}/aaa/bbb/ccc?id=" + $("#id").val();
});