SpringBoot使用freemarker导出word文件方法详解

目录
  • 1、前言
  • 2、需求说明
  • 3、编码
    • 3.1、导入依赖
    • 3.2、接口编写
    • 3.3、工具类
    • 3.4、ftl文件
    • 3.5、测试
  • 4、word转pdf
  • 5、总结

1、前言

在项目中我们有时间需要根据一个word模板文档,批量生成其他的word文档,里面的有些值改变一下而已,那怎么做呢?

2、需求说明

假如说,现在我有个模板文档,内容如下:

现在上面文档里面有如下变量:

  • username:员工姓名
  • idno:身份证号码
  • hireDate:入职日期
  • work:职位
  • endDate:离职日期

现在我需要针对不同的员工一键生成一份离职证明出来,公司章是一张图片,也需要生成进去,下面我们开始测试

3、编码

基础框架代码地址:https://gitee.com/colinWu_java/spring-boot-base.git

我会在此主干基础上开发

3.1、导入依赖

<!--freemarker-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.30</version>
</dependency>

3.2、接口编写

TestController新增下面接口:

/**
     * 根据ftl模板模板下载word文档
     */
@GetMapping("/downloadWord")
public void downloadWord(HttpServletResponse response){
    Map<String, Object> map = new HashMap<>();
    map.put("username", "王天霸");//姓名
    map.put("idno", "429004199601521245");//身份证号
    map.put("hireDate", "2021年12月12日");//入职日期
    map.put("work", "Java软件工程师");//职务
    map.put("endDate", "2022年11月25日");//离职日期
    map.put("imageData", Tools.getBase64ByPath("D:\\demo\\test.png"));//盖章Base64数据(不包含头信息)
    try {
        FreemarkerExportWordUtil.exportWord(response, map, "离职证明.doc", "EmploymentSeparationCertificate.ftl");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

D:\demo\test.png这张图片就是下面这张图片:

3.3、工具类

Tools工具类:

package org.wujiangbo.utils;
import org.wujiangbo.domain.user.User;
import sun.misc.BASE64Encoder;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>工具类</p>
 */
public class Tools {
    /**
     * 获得指定图片文件的base64编码数据
     * @param filePath 文件路径
     * @return base64编码数据
     */
    public static String getBase64ByPath(String filePath) {
        if(!hasLength(filePath)){
            return "";
        }
        File file = new File(filePath);
        if(!file.exists()) {
            return "";
        }
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(file);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        try {
            assert in != null;
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }
    /**
     * @desc 判断字符串是否有长度
     */
    public static boolean hasLength(String str) {
        return org.springframework.util.StringUtils.hasLength(str);
    }
}

FreemarkerExportWordUtil工具类:

package org.wujiangbo.utils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
 * 模板word导出,工具类
 */
public class FreemarkerExportWordUtil {
    private static Configuration configuration = null;
    static {
        configuration = new Configuration(new Version("2.3.0"));
        configuration.setDefaultEncoding("utf-8");
        //获取模板路径    setClassForTemplateLoading 这个方法默认路径是webRoot 路径下
        configuration.setClassForTemplateLoading(FreemarkerExportWordUtil.class, "/templates");
    }
    private FreemarkerExportWordUtil() {
        throw new AssertionError();
    }
    /**
     * 根据 /resources/templates 目录下的ftl模板文件生成文件并写到客户端进行下载
     * @param response HttpServletResponse
     * @param map 数据集合
     * @param fileName 用户下载到的文件名称
     * @param ftlFileName ftl模板文件名称
     * @throws IOException
     */
    public static void exportWord(HttpServletResponse response, Map map, String fileName, String ftlFileName) throws IOException {
        Template freemarkerTemplate = configuration.getTemplate(ftlFileName);
        // 调用工具类的createDoc方法生成Word文档
        File file = createDoc(map, freemarkerTemplate);
        //将word文档写到前端
        download(file.getAbsolutePath(), response, fileName);
    }
    private static File createDoc(Map<?, ?> dataMap, Template template) {
        //临时文件
        String name = "template.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;
    }
    //下载文件的公共方法
    public static void download(String filePath, HttpServletResponse response, String fileName) {
        try {
            setAttachmentResponseHeader(response, fileName);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try(
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
                // 输出流
                BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
        ){
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = bis.read(buff)) > 0) {
                bos.write(buff, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 下载文件名重新编码
     * @param response 响应对象
     * @param realFileName 真实文件名
     * @return
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
    {
        String percentEncodedFileName = percentEncode(realFileName);
        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=")
                .append(percentEncodedFileName)
                .append(";")
                .append("filename*=")
                .append("utf-8''")
                .append(percentEncodedFileName);
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
    }
    /**
     * 百分号编码工具方法
     *
     * @param s 需要百分号编码的字符串
     * @return 百分号编码后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException
    {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }
}

3.4、ftl文件

那么如何制作出ftl模板文件呢?很简单,跟着下面步骤做即可

1、首先新建一个demo.doc文档,然后内容像下面这样写好:

2、将该word文档导出成demo.xml文档,如下:

然后:

这样桌面就会多一个demo.xml文件,此时关闭demo.doc文件,打开demo.xml文件进行编辑

3、修改Demo.xml文件

在demo.xml文件中找到刚才所有的变量,然后都用 包 裹 一 下 , 如 : u s e r n a m e 改 成 {}包裹一下,如:username改成 包裹一下,如:username改成{username},idno改成${idno},等等,全部改完

最后搜索pkg:binaryData字符串,用这个包裹着很大一段字符串,那就是文档中公章图片的Base64格式数据,我们将其全部删除,用${imageData}变量代替即可,待会从代码中给这个变量赋值即可,就可以将真正的公章图片替换到文档中了,而且图片大小格式什么的,都会和模板文档中保持一致,所以模板文档的格式先调整后之后再另存为xml文件

修改完成之后,将文件的后缀名由xml改成ftl,然后拷贝到项目resources下的templates目录下,我这里改成:EmploymentSeparationCertificate.ftl了

3.5、测试

打开浏览器,访问接口:http://localhost:8001/downloadWord,就可以下载一个word文档了,打开后内容如下:

OK,到此测试成功了

4、word转pdf

有些场景需要导出pdf,那么就需要将生成的临时word文件转成pdf后再导出了,下面就介绍一下word转成pdf的方法吧

首先需要导入依赖:

<dependency>
    <groupId>com.documents4j</groupId>
    <artifactId>documents4j-local</artifactId>
    <version>1.0.3</version>
</dependency>
<dependency>
    <groupId>com.documents4j</groupId>
    <artifactId>documents4j-transformer-msoffice-word</artifactId>
    <version>1.0.3</version>
</dependency>

工具类:

/**
     * word文档转成PDF文档
     * @param wordPath word文档路径
     * @param pdfPath pdf文档路径
     */
public static void word2pdf(String wordPath, String pdfPath){
    File inputWord = new File(wordPath);
    File outputFile = new File(pdfPath);
    InputStream docxInputStream = null;
    OutputStream outputStream = null;
    IConverter converter = null;
    try  {
        docxInputStream = new FileInputStream(inputWord);
        outputStream = new FileOutputStream(outputFile);
        converter = LocalConverter.builder().build();
        converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
        outputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
        log.error("word文档转成PDF文档时,发生异常:{}", e.getLocalizedMessage());
    } finally {
        //关闭资源
        try {
            if(docxInputStream != null){
                docxInputStream.close();
            }
            if(outputStream != null){
                outputStream.close();
            }
            if(converter != null){
                converter.shutDown();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

需要注意的是:要使用这个工具类的话,运行这个代码的机器上需要安装WPS或者office软件,否则转换过程中会报错(这可能是一个小瑕疵,我正在寻找其他更加优雅的转换方案,有更好办法的小伙伴,欢迎留言)

我们就调用这个工具类将刚才生成的word文档转成pdf,成功之后内容如下:

内容和word文档一致,测试成功

5、总结

本文主要介绍了根据word模板如何导出word文件,已经将word文档如何转成pdf文件大家赶紧练习起来吧

到此这篇关于SpringBoot使用freemarker导出word文件方法详解的文章就介绍到这了,更多相关SpringBoot导出word内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Springboot整合PageOffice 实现word在线编辑保存功能

    目录 一.查看官网 二.查看下载包 三.测试 四.gitee地址 一.查看官网 http://www.zhuozhengsoft.com/ 点击首页下载,进入页面: 最新得5.2,我们就下载5.2版本进行测试. 二.查看下载包 Samples5 为示例文件.放入tomcat中得webapps可以直接访问. localhost:8080/Samples5/index.html集成文件 里面有我们需要jar包 新建springboot项目以及简单测试这里就不多说了. 1.springboot 引入

  • 解决springboot 连接 mysql 时报错 using password: NO的方案

    最近使用 springboot 配置 mysql 时出现了一个错误 Access denied for user ''@'localhost' (using password: YES) 或者 Access denied for user ''@'localhost' (using password: NO) 经发现这是 springboot 中 yml 语法的的一个坑,在我现在用的最新版本2.2.4 的springBoot中所推荐 yml 的格式是 data-username: root da

  • SpringBoot如何实现word文档转pdf

    目录 一.背景 二.方案选择 1.Spire.Doc for Java方案 2.docx4j方案 3.jodconverter+LibreOffice 方案 4.其他 三.实操 1.docx4j 2.poi-tl+jodconverter+LibreOffice 方案 四.结论 1.docx4j方案 2.jodconverter+LibreOffice 方案 一.背景 项目中有个需求大体意思是,上传一个word模板,根据word模板合成word文件,再将word文件转为pdf. 二.方案选择 1

  • SpringBoot之Helloword 快速搭建一个web项目(图文)

    背景: Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. Spring Boot(英文中是"引导"的意思),是用来简化Spring应用的搭建到开发的过程.应用开箱即用,只要通过 "just

  • 1秒钟实现Springboot 替换/写入 word文档里面的文字、图片功能

    目录 前言 正文 前言 图片加水印:Springboot 图片需要添加水印,怎么办? 1秒就实现 那么word文档替换文字.插入图片,当然也是1秒钟了(jar包引入,工具类代码复制粘贴,调试,完事). 事不宜迟,开始敲代码. 正文 本篇内容: 1.word文档 替换内容里面的文字 (模板占位符方式传参替换) 2.word文档 插入图片 (指定位置传参插入) ① pom.xml 引入依赖: <dependency> <groupId>org.apache.poi</groupI

  • SpringBoot如何基于POI-tl和word模板导出庞大的Word文件

    目录 前言 知识准备 什么是poi-tl poi-tl的TDO模式 Template:模板 Data-model:数据 Output:输出 实现案例 Pom依赖 导出基于template的word 导出markdown为word 前言 poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性.本文主要介绍通过SpringBoot集成poi-tl实现模板方式的Word导出功能. 知识准备 需要理解文件上

  • Java SpringBoot集成文件之如何使用POI导出Word文档

    目录 前言 知识准备 什么是POI 实现案例 Pom依赖 导出Word 前言 通过Apache POI导出excel,而Apache POI包含是操作Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API.所以也是可以通过POI来导出word的.本文主要介绍通过SpringBoot集成POI工具实现Word的导出功能. 知识准备 需要理解Apache POI遵循的标准(Office Open XML(OOXML)标准和微软的OLE 2复合文档

  • 使用Springboot实现word在线编辑保存

    目录 一.查看官网 二.查看下载包 1.springboot 引入 pageoffice5.2.0.12.jar 2.springboot 引入thymleaf 3.编写配置文件 4.编写 index.html 和 word.html 4.1 index.html 4.2 word.html 5.编写PageOfficeController 6.application.yml 配置 7.注意 项目结构 三.测试 输入网址 注意事项 四.gitee地址 总结 一.查看官网 http://www.z

  • SpringBoot使用freemarker导出word文件方法详解

    目录 1.前言 2.需求说明 3.编码 3.1.导入依赖 3.2.接口编写 3.3.工具类 3.4.ftl文件 3.5.测试 4.word转pdf 5.总结 1.前言 在项目中我们有时间需要根据一个word模板文档,批量生成其他的word文档,里面的有些值改变一下而已,那怎么做呢? 2.需求说明 假如说,现在我有个模板文档,内容如下: 现在上面文档里面有如下变量: username:员工姓名 idno:身份证号码 hireDate:入职日期 work:职位 endDate:离职日期 现在我需要针

  • SpringBoot导入导出数据实现方法详解

    今天给大家带来的是一个 SpringBoot导入导出数据 首先我们先创建项目 注意:创建SpringBoot项目时一定要联网不然会报错 项目创建好后我们首先对 application.yml 进行编译 server:  port: 8081# mysqlspring:  datasource:    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://127.0.0.1:3306/dvd?characterEncodi

  • Java使用POI实现导出Excel的方法详解

    目录 一.前景 二.概念 2.1. 简介 2.2.Excel版本和相关对象 2.3.WorkBook 2.4.POI依赖 三.POI - 写 3.1.代码示例 3.2. 性能对比 3.3. 测试rowAccessWindowSize 3.4. 导出Excel样式设置 四.POI - 读 4.1.代码示例 4.2.读取不同的数据类型 4.3.读取公式 五.POI - 遇到的坑 一.前景 在项目开发中往往需要使用到Excel的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据

  • SpringBoot注入自定义的配置文件的方法详解

    目录 一.简介 二.代码实践 2.1 通过@value注解实现参数加载 2.2 通过@ConfigurationProperties注解实现参数加载 2.3 通过@PropertySource注解实现配置文件加载 2.4 通过自定义环境处理类,实现配置文件的加载 2.5 最后,我们来介绍一下yml文件读取 一.简介 在实际的项目开发过程中,我们经常需要将某些变量从代码里面抽离出来,放在配置文件里面,以便更加统一.灵活的管理服务配置信息.比如,数据库.eureka.zookeeper.redis.

  • SpringBoot实现项目文件上传的方法详解

    目录 一.首先抛出问题 二.解决思路 三.直接看源码就懂了,下面是controller 四.结尾 一.首先抛出问题 以阿里云oss文件上传为例,假设我的需求是这样的,我需要发布一条动态,这条动态呢可以是图片.语音.视频,3种类型,每种类型的上传我必须要限制它的文件大小,超过了我就不能让他上传的.如果传统的方式,那就是创建3个上传类型bucket对应图片.语音和视频,其实这种做法是可以的,但是怎么说呢,还不够优雅,如果当这个动态有越来越多种类型,你是不是要建立N个类型对应呢,所以就会使得bucke

  • Python实现PDF转Word的方法详解

    由于PDF的文件大多都是只读文件,有时候为了满足可以编辑的需要通常可以将PDF文件直接转换成Word文件进行操作. 看了网络上面的python转换PDF文件为Word的相关文章感觉都比较复杂,并且关于一些图表的使用还要进行特殊的处理. 本篇文章主要讲解关于如何使用python是实现将PDF转换成Word的业务过程,这次没有使用GUI应用的操作. 由于可能存在版本冲突的问题,这里将开发过程中需要使用的python非标准库的版本列举出来. python内核版本:3.6.8 PyMuPDF版本:1.1

  • jsp按格式导出doc文件实例详解

    jsp按格式导出doc文件实例详解 原理:doc文件其实可以保存为xml文件,该xml文件用字符串表示了doc文件的表现形式,我们只需要用Java将那些要填的内容替换掉然后下载给客户就行了. 1.首先是按照你的文档填写好数据. 2.将文档另存为xml文件,然后编辑该xml文件,将填好的内容用某种格式替换,如:将名字张三替换成${name} 3.读取文件,将文件中的${name}替换成真正的名字. 4.下载. 接下来看代码: 首先是那个转换类 package com.my.util; import

  • SpringBoot注入配置文件的3种方法详解

    这篇文章主要介绍了SpringBoot注入配置文件的3种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 方案1:@ConfigurationProperties+@Component 定义spring的一个实体bean装载配置文件信息,其它要使用配置信息是注入该实体bean /** * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配

  • Spring Boot读取resources目录文件方法详解

    这篇文章主要介绍了Spring Boot读取resources目录文件方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在Java编码过程中,我们常常希望读取项目内的配置文件,按照Maven的习惯,这些文件一般放在项目的src/main/resources下,因此,合同协议PDF模板.Excel格式的统计报表等模板的存放位置是resources/template/test.pdf,下面提供两种读取方式,它们分别在windows和Linux

  • Python安装tar.gz格式文件方法详解

    这篇文章主要介绍了Python安装tar.gz格式文件方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 有的库没有找到对应的.whl格式文件,只有.tar.gz格式文件,接下来总结下该类型文件的安装. 以robotframework-ride-1.7.4.tar.gz为例 (1)下载robotframework-ride-1.7.4.tar.gz文件,将此文件放到Python下的Lib文件中: (2)进入已解压的robotframewor

随机推荐