天天看點

FreeMarker模闆導出Word或Excel檔案

一、前言

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();
});