首先先上成功的代码,然后再讲碰到的各种问题

  1. 导入freemarker的maven坐标
<!--freemarker 生成word-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
  1. 新建一个freemarker的配置类
    这里我数据里有特殊字符,特地设置了< > # @ \ / 等自动转义
package com.demo.app.config.freemarker;

import freemarker.core.XMLOutputFormat;
import freemarker.template.Configuration;
import org.springframework.context.annotation.Bean;

/**
 * @program: demo
 * @description:
 * @author: fbl
 * @create: 2021-12-23 14:19
 **/
@org.springframework.context.annotation.Configuration
public class WordConfig {

    @Bean
    public Configuration wordConfiguration(){
        Configuration result = new Configuration();
        result.setDefaultEncoding("utf-8");
        //设置模板加载器
        result.setClassForTemplateLoading(this.getClass(), "/word");
        // 设置Freemarker格式化模板 > < 等特殊符号转义
        result.setOutputFormat(XMLOutputFormat.INSTANCE);
        return result;
    }

}
  1. 接下来整理模板
    3.1 新建一个word,将数据填充在需要的位置,如下图
    3.2 将word另存为xml文件,再接着改名为ftl文件后缀,粘贴到项目中,路径在上面的配置代码中有,是根目录下的word文件夹中

    这个ftl文件实际就是xml文件,里面好多数据还需要处理一下,需要用到freemarker语法

例如:

// 符号转义
	比较:> gt,< lt,<= lte, >= gte
	// 处理列表循环取出数据 相当于for
   <#list data.elementDetails as detali></#list>
   // 另一种循环 相当于fori
   <#list 1..(data.elementDetails!?size-1) as i>
   // 集合的长度
   empList?size 
   // 跳出循环
   <#break>
   // 取出数组下标相符的数据
   ${data.elementDetails[0].num!}
   // if判断决定值是什么
   <#if data.stable.stableFlag>稳定<#else>不稳定</#if>
   // 非空判断 ??
   <#if data.biology??>${data.biology.poison!""}</#if>
   // 字符串包含
    <#if t.safetyCheck?contains("5")> ...操作</#if>
  1. 接下来是service层用数据渲染模板,controller就是调service没有什么可写的
@Resource(name = "wordConfiguration")
   private Configuration wordConfiguration;

  public void wordExport(HttpServletResponse response, Integer id){
       // 搜集需要导出的数据
       MsdsWordExportDto wordData = getWordData(id);
       // 枚举数据处理
       parseWordData(wordData);

       Map<String, Object> dataModel = new HashMap<>();
       dataModel.put("data", wordData);

       response.setCharacterEncoding("UTF-8");
       response.setHeader("Content-Disposition", "attachment; filename=chemical.doc");
       //加载模板
       try {
           Template template = wordConfiguration.getTemplate("化学品安全技术说明书模板测试.ftl", "utf-8");
           template.process(dataModel, response.getWriter());
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

更新一下生成word文档中带图片怎么办

  1. 首先新建一个word文档,里面有张图片
  2. 接着另存为xml,改名ftl(上述操作)
  3. 找到ftl文件存储图片的地方,是base64格式的密文

    把它改为你传入的参数,当然参数也要是base64格式的字符串
    以下是转换base64的代码,传入的参数是图片的url,类似于:http://172.16.0.72:8003/file/1.jpg
/**
     * 图片导出word 使用base64
     *
     * @param imgFile
     * @return
     */
    private String getImgFileToBase64(String imgFile) {
        //将图片文件转化为字节数组字符串,并对其进行Base64编码处理
        byte[] buffer = null;
        // 获取图片路径
        int lastIndexOf = imgFile.lastIndexOf('/');
        String fileName = imgFile.substring(lastIndexOf + 1);
        String filePathString = path + fileName;

        //读取图片字节数组
        try (InputStream inputStream = new FileInputStream(filePathString)){
            buffer = new byte[inputStream.available()];
            inputStream.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        return new BASE64Encoder().encode(buffer);
    }

又做了一个freemarker导出work多图片的,又加深了理解

freemarker生成word文档带格式 freemarker生成word打不开_#if

在这里插入base64之后

上面会有引用

freemarker生成word文档带格式 freemarker生成word打不开_intellij-idea_02

搜索id,发现word中引用这张图片

freemarker生成word文档带格式 freemarker生成word打不开_intellij-idea_03