天天看点

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