Freemarker导出Word文档

做了一个导出Word功能,记录下遇见的坑和技术
一开始我用的poi

1.模板准备

1.1将你需要导出的word模板填写部分用字段去代理 ${data?if_exists}

word文档准备

注意:${data}需按顺序写,否则生成xml文档会分开。如果导出需要用到图片在word文档中先插入图片占位.?if_exists空判断

1.2保存成xml文档

保存word.xml文档

1.3将xml放入项目中的Resource/wordTemplate目录下面,然后修改文件后缀名为ftl

在这里插入图片描述

1.4 将ftl文件中的这长串字符选中,替换成图片字段${image}

在这里插入图片描述

注意:如果在文件中出现中文乱码或者导出成功之后乱码的情况,先在wordTemplate目录下创建一个ftl文件,然后将做好的数据复制到新的ftl里面即可。
ftl中会出现很多报红,这个无需处理,如果有强迫症的需要将一条条报红信息添加到idea配置中

在这里插入图片描述

2.导入依赖

		<!-- 引入 freemarker 模板依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>

3.创建wordUtils工具类

import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Encoder;

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

/**
 * word导出工具
 */
public class WordUtils {
    //配置信息,代码本身写的还是很可读的,就不过多注解了
    private static Configuration configuration;
    //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置
    // private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";
//    private static final String templateFolder = "H:/web/src/main/webapp/WEB-INF/templates";

    static {
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(WordUtils.class, "/wordTemplate");
//            configuration.setDirectoryForTemplateLoading(new File(templateFolder));
    }

    private WordUtils() {
        throw new AssertionError();
    }

    public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException {
        Template freemarkerTemplate = configuration.getTemplate(ftlFile);
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            // 调用工具类的createDoc方法生成Word文档
            file = createDoc(map, freemarkerTemplate);
            fin = new FileInputStream(file);

            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            // 设置浏览器以下载的方式处理该文件名
            String fileName = title + ".doc";

            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));

            out = response.getOutputStream();
            byte[] buffer = new byte[512]; // 缓冲区
            int bytesToRead = -1;
            // 通过循环将读入的Word文件的内容输出到浏览器中
            while ((bytesToRead = fin.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);
            }
        } finally {
            if (fin != null) fin.close();
            if (out != null) out.close();
            if (file != null) file.delete(); // 删除临时文件
        }
    }

    private static File createDoc(Map<?, ?> dataMap, Template template) {
        String name = "WordTemplate.doc";
        File f = new File(name);
        Template t = template;
        try {
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
            t.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
        return f;
    }
    /**
     * 将图片内容转换成Base64编码的字符串
     *
     * @param imageFile 图片文件的全路径名称
     * @return 转换成Base64编码的图片内容字符串
     */
    public static String getImageBase64String(String imageFile) {
        if (StringUtils.isEmpty(imageFile)) {
            return "";
        }
        File file = new File(imageFile);
        if (!file.exists()) {
            return "";
        }
        InputStream is = null;
        byte[] data = null;
        try {
            is = new FileInputStream(file);
            data = new byte[is.available()];
            is.read(data);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }
}
这块是网上找来直接用到

4.Controller

@GetMapping("/word/download")
    @AnonymousAccess
    public void wordDownload(Long id, HttpServletRequest request, HttpServletResponse response){
        service.wordDownload(id,request,response);
    }

5.Service

/**
     * 导出异常详情word文档
     *
     * @param id
     */
    @Override
    public void wordDownload(Long id, HttpServletRequest request, HttpServletResponse response) {
        try {
            if (id == null) {
                throw new PtException("请求参数错误!");
            }
            //模板数据
            Map<String, Object> data = new HashMap<>();
            data.put("data", id);//key:${data} value :值
            data.put("image", WordUtils.getImageBase64String(file.getFilePath()));//查询出来的地址
            WordUtils.exportMillCertificateWord(request,response,data,"详情","displayScreenException.ftl");
        } catch (Exception e) {
            throw new PtException("操作异常", e);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java白菜治

祝愿赞赏大佬薪资翻倍

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值