freemarker实现word导出功能

1.为什么选择freeMarker

1.导出的word模板固定,只是数据改变
2.快速简单

2.freeMarker是什么

FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。

目前企业中:主要用Freemarker做静态页面或是页面展示

3.怎么使用freemarker

  • 引入jar,这里用的是org.freemarker.freemarker下
//引入freemarker
    compile group: 'org.freemarker', name: 'freemarker', version: '2.3.28'
  • 模板生成和创建的工具类
package com.xxxx.xxxxx.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;

/**
 * word 文档生成和下载工具类
 */
public class WordExprotUtils {
    /**
     * 浏览器下载 word文档
     * @param dataMap  用map集合来保存,word中需要加载展示的动态数据
     * @param templateName word模板名称,例如:complainTemplate.ftl
     * @param filePath 文件生成word文件的目标路径,例如:C:\Users\WangChong\Desktop(我们的桌面路径)
     * @param fileName 文件生成word文件名称
     * @param fileSuffixName 文件生成word文件名称的后缀名
     */
    public static void downLoadWord(Map<?,?> dataMap,String templateName,String filePath,String fileName,String fileSuffixName,HttpServletResponse response){
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            //生产word文件
            file = createaWord(dataMap,filePath,fileName,fileSuffixName,templateName);
            //浏览器下载方式(下载的文件名可以自定命名,这里使用上一步word文件名)
            fin = new FileInputStream(file);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName+fileSuffixName, "UTF-8"))));
            out = response.getOutputStream();
            byte[] buffer = new byte[1024];  // 读写缓冲区
            int bytesToRead = -1;
            while((bytesToRead = fin.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);// 通过循环将读入的Word文件的内容输出到浏览器中
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(fin != null) {
                    fin.close();// 关闭文件输入流
                }
                if(out != null) {
                    out.close();// 关闭文件输出流
                }
                if(file != null) {
                    file.delete(); // 删除临时文件
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *创建word文档
     * @param dataMap 用map集合来保存,word中需要加载展示的动态数据
     * @param filePath 生成word文件的目标路径,例如:C:\Users\WangChong\Desktop(我们的桌面路径)
     * @param fileName  生成word文件名称 例如:建议详情
     * @param fileSuffixName 生成word文件名称的后缀名 例如:.doc 或 .docx
     * @param templateName   word模板名称,例如:complainTemplate.ftl
     * @return file 返回创建的文件
     */
    private static File createaWord(Map<?, ?> dataMap,String filePath,String fileName,String fileSuffixName,String templateName) {
        Template freemarkerTemplate = null;
        File file = null;
        FileOutputStream fileOutputStream = null;
        Writer writer = null;
        File templateFile = null; //模板文件
        try {
            //1.配置类配置
            Configuration  configuration = new Configuration(Configuration.VERSION_2_3_28);//初始化配置 需要指定配置的版本
            configuration.setDefaultEncoding("utf-8");//设置默认的编码方式为utf-8
            //---------------------------------解决jar获取不到资源路径文件[开始]--------------------------------
            //解决思路:将模板放置在磁盘上读取
            // 首先获取类路径下的模板文件将其转化为输入流的方式
            // 然后在使用的计算上创建一个空的模板文件,这个文件可以是作为临时文件(即创建完使用后删除),也可以作为电脑磁盘上的永久文件。这里使用永久文件,防止频繁创建删除消耗磁盘寿命。
            // 再然后 将 上面的输入流复制到创建的模板文件。
            ClassPathResource classPathResource = new ClassPathResource("/templates/freeMarkerTemplate/"+templateName);
            InputStream inputStream = classPathResource.getInputStream();//先转输入流
            String templateDir = filePath+"/freeMarkerTemplate";//模板文件目录
            File dir = new File(filePath+"/freeMarkerTemplate");//目录不存在则创建
            if (!dir.exists()){
                dir.mkdirs();
            }
            templateFile = new File(templateDir+File.separator+templateName);//生成模板文件
            templateFile.createNewFile();//当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
            FileUtils.copyInputStreamToFile(inputStream, templateFile);//将流复制到目标文件后并关闭流
            IOUtils.closeQuietly(inputStream);//手动关闭
            //---------------------------------解决jar获取不到资源路径文件[结束]--------------------------------
            //2.设置模板
            configuration.setDirectoryForTemplateLoading(dir);//注意这里放的是模板文件的目录,而不是具体到模板文件
            //3.获取模板
            freemarkerTemplate  = configuration.getTemplate(templateName);
            //4.生成Word文档
            file = new File(templateDir+File.separator+fileName+fileSuffixName);//生成的word文档绝对路径
            fileOutputStream = new FileOutputStream(file);
            writer = new OutputStreamWriter(fileOutputStream, "utf-8");// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            freemarkerTemplate.process(dataMap, writer);//生成word文档
        } catch (TemplateException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fileOutputStream != null){
                    fileOutputStream.close();//关闭文件输出流
                }
                if(writer != null){
                    writer.close();//关闭写入流
                }
//                if(null != somethingFile){
//                    somethingFile.delete();//删除模板文件,这里不删除
//                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return file;
    }




}


  • 制作模板----.ftl文件
1.打开word ,绘制好模板样式,并在要动态展示的地方输入对应的变量名称。例如:${name}

在这里插入图片描述

2.另存为‘xml文件(*.xml)’文件

3.用编译器打开上一步的文件,检查变量是否都对(即和原来给的形式一样:例如${name} 符号之间没有多余的字符,如果有要将其删除)
在这里插入图片描述
4.重命名为以.ftl为后缀的文件。

在这里插入图片描述

参考文章:
https://www.jianshu.com/p/20fd71b2e6a0

可以使用 Apache POI 和 FreeMarker实现 Word 导出。具体步骤如下: 1. 引入依赖: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.31</version> </dependency> ``` 2. 编写模板文件,例如 `template.ftl`: ```xml <?xml version="1.0" encoding="UTF-8"?> <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"> <w:body> <w:p> <w:r> <w:t>${title}</w:t> </w:r> </w:p> <w:p> <w:r> <w:t>${content}</w:t> </w:r> </w:p> </w:body> </w:document> ``` 3. 编写 Java 代码: ```java import freemarker.template.Configuration; import freemarker.template.Template; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import java.io.*; import java.util.HashMap; import java.util.Map; public class WordExportUtil { public static void export(Map<String, Object> dataMap, String templatePath, String outputPath) throws Exception { // 1. 创建 Configuration 对象 Configuration configuration = new Configuration(Configuration.VERSION_2_3_31); configuration.setDefaultEncoding("UTF-8"); // 2. 加载模板文件 Template template = configuration.getTemplate(templatePath); // 3. 创建 Word 文档对象 XWPFDocument document = new XWPFDocument(); // 4. 填充数据到 Word 文档中 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8"); template.process(dataMap, outputStreamWriter); outputStreamWriter.flush(); ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) { XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); run.setText(line); } // 5. 输出 Word 文档 FileOutputStream fileOutputStream = new FileOutputStream(outputPath); document.write(fileOutputStream); fileOutputStream.close(); } } ``` 其中,`dataMap` 是模板中需要填充的数据,`templatePath` 是模板文件的路径,`outputPath` 是输出文件的路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值