【笑小枫的SpringBoot系列】【十五】SpringBoot根据模板生成Word

通过maven引入需要的依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-freemarkerartifactId>
dependency>

创建导出模版

1、首先创建一个word模版文档,模版如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sJmfXW8C-1668394191130)(D:\zhangfuzeng\code\Java-Notes\src\note\images\exportword\01.jpg)]

word模版地址:点击下载

注意word中的占位符的格式,就是freemaker的格式

详细解释如下:

  • 文字处理:

直接用${} 中间为替换的字段名。

如果直接在word里面定义${title},在转换成xml的时候有可能会被一些编码隔开,这个时候只需要用word打开xml,将这些内容重新输入一遍。

强烈建议用IDE打开,然后格式化下,在进行检查处理,能用搜索尽量搜索,xml的格式里面有太多的代码,不要硬刚

  • 图片处理:

需要在word文档模版中插入图片

将word转换成xml后,打开xml,会将我们的图片转换成长长的一段base64。

我们把base64换成我们的${pic}就可以了,pic为字段名,可任意替换

  • 列表处理:

需要在word文档模版中插入表格

找到第二个,第一行是我们的标题,在其前面添加 <#list peopleList as list> 其中 peopleList是传入list的集合名称 list 是别名。

参数取值为:${list.name}这样。

在与配对的后面添加。 语法同freemaker的for循环语法

创建ftl模板

将上述word文档另存为test.xml格式,另存完之后可以用浏览器打开test.xml文件,查看我们的占位符是否标准

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IpzL5rAb-1668394191133)(D:\zhangfuzeng\code\Java-Notes\src\note\images\exportword\03.jpg)]

注意:占位符有时候会发生被隔开的情况,如下图:

SpringCloud江湖

图片的替换同上面的说明,图片为一串长长的base64,如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5VtuFSJQ-1668394191134)(D:\zhangfuzeng\code\Java-Notes\src\note\images\exportword\02.jpg)]

然后将文件放置resources/templates目录下。

放置在resource目录下即可,剩下的目录根据自己需求定制。注意要与WordUtil.java中的目录对应。

编写程序

通用的导出工具类

在util包下创建WordUtil.java工具类,

package com.maple.demo.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import static freemarker.template.Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS;

/**
 * @author 笑小枫
 * @date 2022/7/27
 * @see https://www.xiaoxiaofeng.com
 */
public class WordUtil {
    private final Configuration configuration;

    public WordUtil() {
        configuration = new Configuration(DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        configuration.setDefaultEncoding("UTF-8");
    }

    public void createWord(Map<String, Object> dataMap, String templateName, String fileName) {
        // 模板文件所在路径
        configuration.setClassForTemplateLoading(this.getClass(), "/templates");
        Template t = null;
        try {
            // 获取模板文件
            t = configuration.getTemplate(templateName, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 导出文件
        File outFile = new File(fileName);
        try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8))) {
            if (t != null) {
                // 将填充数据填入模板文件并输出到目标文件
                t.process(dataMap, out);
            }
        } catch (IOException | TemplateException e1) {
            e1.printStackTrace();
        }
    }
}
请求接口

controller包下创建TestWordController.java

其中用到了之前文章的文件转base64,参考文章15.Base64与File互转

package com.maple.demo.controller;

import com.maple.demo.util.Base64Util;
import com.maple.demo.util.WordUtil;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author 笑小枫
 * @date 2022/7/27
 * @see https://www.xiaoxiaofeng.com
 */
@RestController
@AllArgsConstructor
@RequestMapping("/example")
@Api(tags = "实例演示-根据模板生成word")
public class TestWordController {
    /**
     * 文字处理:
     * 直接用${} 中间为替换的字段名。
     * 如果直接在word里面定义${title},在转换成xml的时候有可能会被一些编码隔开,这个时候只需要用word打开xml,将这些内容重新输入一遍。
     * 可以用浏览器打开xml,检出自己定义的${}的内容是否都在一起,是否有被编码隔开的情况。
     * 图片处理:
     * 需要在word文档模版中插入图片
     * 将word转换成xml后,打开xml,会将我们的图片转换成长长的一段base64。
     * 我们把base64换成我们的${pic}就可以了,pic为字段名,可任意替换
     * 列表处理:
     * 需要在word文档模版中插入表格
     * 找到第二个,在其前面添加 <#list peopleList as list> 其中 peopleList是传入list的集合名称 list 是别名。
     * 参数取值为:${list.name}这样。
     * 在与配对的后面添加。 语法同freemaker的for循环语法
     */
    @GetMapping("/exportWord")
    public void exportWord(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1.创建临时文件夹
        String rootPath = request.getSession().getServletContext().getRealPath("/");
        String fileName = UUID.randomUUID().toString().replace("-", "");

        // 处理图片信息,将图片转为base64字符串
        File imageFile = new File("D:\\xiaoxiaofeng.jpg");
        String base64 = Base64Util.fileToBase64(imageFile);

        // 处理表格的数据信息
        List<Map<String, Object>> list = new ArrayList<>();
        int size = 5;
        for (int i = 0; i < size; i++) {
            Map<String, Object> map = new HashMap<>(16);
            map.put("nickName", "笑小枫" + i);
            map.put("visitTime", "2022-07-27");
            map.put("isLike", "是");
            map.put("isAttention", "是");
            list.add(map);
        }

        // 加载word中的数据信息
        WordUtil word = new WordUtil();
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("title", "记得关注我哟");
        dataMap.put("email", "[email protected]");
        dataMap.put("name", "笑小枫");
        dataMap.put("createDate", "2022-07-27");
        dataMap.put("pic", base64);
        dataMap.put("peopleList", list);
        word.createWord(dataMap, "word.xml", rootPath + "/" + fileName + ".doc");

        String exportName = "测试word";
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/msword");
        // 设置浏览器以下载的方式处理该文件名
        response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(exportName + ".doc", "UTF-8"))));

        File file = new File(rootPath + "/" + fileName + ".doc");
        try (InputStream fin = new FileInputStream(file);
             ServletOutputStream out = response.getOutputStream()) {
            // 缓冲区
            byte[] buffer = new byte[512];
            int bytesToRead;
            // 通过循环将读入的Word文件的内容输出到浏览器中
            while ((bytesToRead = fin.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 删除临时文件
            file.delete();
        }
    }
}

测试

在浏览器输入http://localhost:6666/example/exportWord便可以看到你的word出来了呦。

导出效果图如下:
【笑小枫的SpringBoot系列】【十五】SpringBoot根据模板生成Word_第1张图片

关于笑小枫

本章到这里结束了,喜欢的朋友关注一下我呦,大伙的支持,就是我坚持写下去的动力。
笑小枫个人博客:https://www.xiaoxiaofeng.com
本文源码:https://github.com/hack-feng/maple-demo

本系列其它文章

本系列的源码已同步在Github:https://github.com/hack-feng/maple-demo

  1. SpringBoot项目创建

  2. SpringBoot配置基于swagger2的knife4j接口文档

  3. SpringBoot集成Mybatis Plus

  4. SpringBoot返回统一结果包装

  5. SpringBoot返回统一异常处理

  6. SpringBoot日志打印Logback详解

  7. SpringBoot控制台自定义banner

  8. SpringBoot集成Redis

  9. SpringBoot用户登录拦截器

  10. SpringBoot处理请求跨域问题

  11. SpringBoot接口日志信息统一记录

  12. SpringBoot导入Excel

  13. SpringBoot导出Excel

  14. SpringBoot发送邮件

  15. SpringBoot根据模板生成Word

  16. SpringBoot生成PDF

  17. SpringBoot文件上传下载

  18. SpringBoot中的Properties配置

你可能感兴趣的:(java,xml,word,java生成word)