文章目录

  • 前言
  • 将docx模板填充数据生成doc文件
    • 1、依赖引入
    • 2、doc文件转换docx,并标注别名
    • 3、编写java代码实现数据填充
  • docx文件填充数据导出pdf(web)
    • 1、依赖引入
    • 2、字体文件
    • 3、编写工具类
    • 4、编写测试接口
  • 请求测试
  • 参考资料

前言

在项目中碰见一个需求,需要将.doc的合同,转换为pdf实现打印与预览功能。

将docx模板填充数据生成doc文件

1、依赖引入

填充docx模板,只需要引入一个pom依赖即可实现。

<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.5.0</version>
</dependency>

2、doc文件转换docx,并标注别名

用office或者wps,创建一个001.doc文件,绘制表格,保存。

更改后缀为.docx,确定后,在指定的位置,表示数据接受变量名称。

如下图所示:

3、编写java代码实现数据填充

import com.deepoove.poi.XWPFTemplate;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;/*** word 填充测试*/
public class TestWord {public static void main(String[] args) throws IOException {Map<String, Object> params = new HashMap<>();params.put("username","xiangjiao1");params.put("password","******");params.put("age",22);params.put("email","专注写bug测试中文");Resource resource = new ClassPathResource("templates_report/001.docx");File file = resource.getFile();// 数据填充XWPFTemplate template = XWPFTemplate.compile(file).render(params);String docOutPath = System.getProperty("user.dir")+File.separator+"springboot-poi"+File.separator+"pdf"+File.separator+ "1.doc";OutputStream outputStream = new FileOutputStream(docOutPath);template.write(outputStream);}
}

运行程序,查看结果。

测试项目结构如下:

docx文件填充数据导出pdf(web)

1、依赖引入

docx模板中填充数据,并导出pdf类型的文件,除了上面的pom依赖之外,还需要引入其他的依赖信息,完整依赖如下所示:

<!-- docx 数据填充生成 doc文件  这个是主要 -->
<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.5.0</version>
</dependency>
<!-- doc 转 pdf -->
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version>
</dependency>
<!-- docx4j docx2pdf -->
<dependency><groupId>org.docx4j</groupId><artifactId>docx4j</artifactId><version>6.1.2</version>
</dependency>
<dependency><groupId>org.docx4j</groupId><artifactId>docx4j-export-fo</artifactId><version>6.0.0</version>
</dependency>

2、字体文件

src\main\resources下创建一个font文件夹,其中放入simsun.ttc字体文件。

3、编写工具类

思想很简单

1、先使用上面的docx模板填充数据生成临时doc文件,
2、再将doc文件转换为pdf文件
3、删除临时文件

【注意:】

为了避免出现多人同时操作,导致文件误删的问题,
需要尽可能地保证临时文件名称的唯一性。

import com.deepoove.poi.XWPFTemplate;
import com.itextpdf.text.*;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.Map;
import java.util.UUID;
import java.util.zip.ZipOutputStream;/*** pdf 导出工具类*/
@Component
@Slf4j
public final class FreeMarkUtils {/*** 根据docx模板填充数据  并生成pdf文件** @param dataMap      数据源* @param docxFile     docx模板的文件名* @return 生成的文件路径*/public static byte[] createDocx2Pdf(Map<String, Object> dataMap, String docxFile) {//输出word文件路径和名称 (临时文件名,本次为测试,最好使用雪花算法生成,或者用uuid)String fileName = UUID.randomUUID().toString() + ".docx";// word 数据填充// 生成docx临时文件final File tempPath = new File(fileName);final File docxTempFile = getTempFile(docxFile);XWPFTemplate template = XWPFTemplate.compile(docxTempFile).render(dataMap);try {template.write(new FileOutputStream(tempPath));} catch (IOException e) {e.printStackTrace();}// word转pdffinal String pdfFile = convertDocx2Pdf(fileName);return getFileOutputStream(new File(pdfFile)).toByteArray();}/*** word(doc)转pdf** @param wordPath doc 生成的临时文件路径* @return 生成的带水印的pdf路径*/public static String convertDocx2Pdf(String wordPath) {OutputStream os = null;InputStream is = null;//输出pdf文件路径和名称  (临时文件  尽可能保证文件名称的唯一性)final String fileName = UUID.randomUUID().toString() + ".pdf";try {is = new FileInputStream(wordPath);WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);Mapper fontMapper = new IdentityPlusMapper();fontMapper.put("隶书", PhysicalFonts.get("LiSu"));fontMapper.put("宋体", PhysicalFonts.get("SimSun"));fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));fontMapper.put("黑体", PhysicalFonts.get("SimHei"));fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));//解决宋体(正文)和宋体(标题)的乱码问题PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));PhysicalFonts.put("新細明體", PhysicalFonts.get("SimSun"));// 字体文件PhysicalFonts.addPhysicalFonts("SimSun", WordUtils.class.getResource("/font/simsun.ttc"));mlPackage.setFontMapper(fontMapper);os = new FileOutputStream(fileName);//docx4j  docx转pdfFOSettings foSettings = Docx4J.createFOSettings();foSettings.setWmlPackage(mlPackage);Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);is.close();//关闭输入流os.close();//关闭输出流} catch (Exception e) {e.printStackTrace();} finally {// 删除docx 临时文件File file = new File(wordPath);if (file != null && file.isFile() && file.exists()) {file.delete();}try {if (is != null) {is.close();}if (os != null) {os.close();}} catch (Exception ex) {ex.printStackTrace();}}return fileName;}/*** 文件转字节输出流** @param outFile 文件* @return*/public static ByteArrayOutputStream getFileOutputStream(File outFile) {// 获取生成临时文件的输出流InputStream input = null;ByteArrayOutputStream bytestream = null;try {input = new FileInputStream(outFile);bytestream = new ByteArrayOutputStream();int ch;while ((ch = input.read()) != -1) {bytestream.write(ch);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {bytestream.close();input.close();log.info("删除临时文件");if (outFile.exists()) {outFile.delete();}} catch (IOException e) {e.printStackTrace();}}return bytestream;}/*** 获取资源文件的临时文件* 资源文件打jar包后,不能直接获取,需要通过流获取生成临时文件** @param fileName 文件路径 templates/xxx.docx* @return*/public static File getTempFile(String fileName) {final File tempFile = new File(fileName);InputStream fontTempStream = null;try {fontTempStream = FreeMarkUtils.class.getClassLoader().getResourceAsStream(fileName);FileUtils.copyInputStreamToFile(fontTempStream, tempFile);} catch (Exception e) {e.printStackTrace();} finally {try {if (fontTempStream != null) {fontTempStream.close();}} catch (IOException e) {e.printStackTrace();}}return tempFile;}/*** 插入图片水印* @param srcByte 已生成PDF的字节数组(流转字节)* @param destFile 生成有水印的临时文件 temp.pdf* @return*/public static FileOutputStream addWaterMark(byte[] srcByte, String destFile) {// 待加水印的文件PdfReader reader = null;// 加完水印的文件PdfStamper stamper = null;FileOutputStream fileOutputStream = null;try {reader = new PdfReader(srcByte);fileOutputStream = new FileOutputStream(destFile);stamper = new PdfStamper(reader, fileOutputStream);int total = reader.getNumberOfPages() + 1;PdfContentByte content;// 设置字体//BaseFont font = BaseFont.createFont();// 循环对每页插入水印for (int i = 1; i < total; i++) {final PdfGState gs = new PdfGState();// 水印的起始content = stamper.getUnderContent(i);// 开始content.beginText();// 设置颜色 默认为蓝色//content.setColorFill(BaseColor.BLUE);// content.setColorFill(Color.GRAY);// 设置字体及字号//content.setFontAndSize(font, 38);// 设置起始位置// content.setTextMatrix(400, 880);//content.setTextMatrix(textWidth, textHeight);// 开始写入水印//content.showTextAligned(Element.ALIGN_LEFT, text, textWidth, textHeight, 45);// 设置水印透明度// 设置笔触字体不透明度为0.4fgs.setStrokeOpacity(0f);Image image = null;image = Image.getInstance("url");// 设置坐标 绝对位置 X Y 这个位置大约在 A4纸 右上角展示LOGOimage.setAbsolutePosition(472, 785);// 设置旋转弧度image.setRotation(0);// 旋转 弧度// 设置旋转角度image.setRotationDegrees(0);// 旋转 角度// 设置等比缩放 图片大小image.scalePercent(4);// 依照比例缩放// image.scaleAbsolute(200,100);//自定义大小// 设置透明度content.setGState(gs);// 添加水印图片content.addImage(image);// 设置透明度content.setGState(gs);//结束设置content.endText();content.stroke();}} catch (IOException e) {e.printStackTrace();} catch (DocumentException e) {e.printStackTrace();} finally {try {stamper.close();fileOutputStream.close();reader.close();} catch (DocumentException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}return fileOutputStream;}
}

4、编写测试接口

import cn.xj.util.FreeMarkUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;@RestController
@RequestMapping("/report")
public class ReportController {@GetMapping("/doc2pdf")public void doc2pdf(HttpServletResponse response) {Map<String, Object> params = new HashMap<>();params.put("username","xiangjiao1");params.put("password","******");params.put("age",22);params.put("email","专注写bug测试中文");final byte[] data = FreeMarkUtils.createDocx2Pdf(params, "templates_report/001.docx");String fileName = UUID.randomUUID().toString() + "_001_test.pdf";generateFile(response, data, fileName);}/*** 下载文件* @param response 相应* @param data 数据* @param fileName 文件名*/private void generateFile(HttpServletResponse response, byte[] data, String fileName) {response.setHeader("content-Type", "application/octet-stream");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName);try {response.getOutputStream().write(data);} catch (IOException e) {e.printStackTrace();} finally {try {response.getOutputStream().close();} catch (IOException e) {e.printStackTrace();}}}
}

请求测试

http://localhost/report/doc2pdf

参考资料

Spring Boot Freemark HTML 生成 PDF、生成水印Logo、docx文件生成PDF,Jar包运行可读取模板文件、字体文件

Springboot —— 根据docx填充生成word文件,并导出pdf相关推荐

  1. PageOffice动态生成Word文件并转换为PDF

    说明:PageOffice是客户端插件,做不到纯后台调用把word转为pdf.但是pageoffice的FileMaker对象可以实现不在客户端打开文件直接转换文件为pdf并保存到服务器端,看起来跟服 ...

  2. java xsl生成word文件_导出生成xsl文件

    public String expData() throws Exception{ List list = subAreaService.findAll(); HSSFWorkbook hssf =  ...

  3. 若依 springboot 使用freemarker生成word文件,并导出下载

    目录 freemarker生成word文件并导出 一.环境准备 二.编写代码 1.实体类 2.mapper.xml文件 3.mapper.java文件 4.Service.java 5.Service ...

  4. Java技术:SpringBoot集成FreeMarker生成word文件

                    今天给大家分享SpringBoot集成FreeMarker模板引擎生成word文件的用法,感兴趣的可以学一下,完整源码地址在文章末尾处,欢迎互相沟通交流! 一.什么是F ...

  5. SpringBoot集成Freemarker,并使用API生成word文件

    Spring Boot 集成 Freemarker spring boot 集成 freemarker 的简单使用 使用freemarker生成word文件 目录 Spring Boot 集成 Fre ...

  6. springboot项目使用beetl模板引擎生成word文件

    一.详情可查看官网 1.官方网址:beetl官网 一.简单测试beetl生成word文件 1.在springboot项目中添加beetl的依赖 <dependency><groupI ...

  7. Python 自动化教程(5) : 自动生成Word文件

    系列教程: Python 自动化教程(1) 概述,第一篇 Excel自动化 Python 自动化教程(2) : Excel自动化:使用pandas库 Python 自动化教程(3) : 自动生成PPT ...

  8. java 根据word模板生成word文件

    Java可以使用Apache POI库来生成Word文件,并且也可以使用freemarker等模板引擎来实现根据Word模板生成Word文件的功能. 下面是一个简单的示例代码,可以帮助您快速入门. 模 ...

  9. java批量导出word_java 批量生成word 文件

    最近在工作中遇到一个需求,我有一个拥有3000行数据的excel文件和一个word模板. 我需要将excel文件中的每一行数据填充到word模板文件中生成一个Word文件. 考虑到数据量较大且需求有可 ...

最新文章

  1. css美化单选款、复选框
  2. DL之self-attention:self-attention自注意力机制的简介、应用之详细攻略
  3. centos6上虚拟主机的实现
  4. 股市孙子兵法(收藏)
  5. mysql更新数据 update格式和alter对比
  6. Quick Cocos2dx 场景转换问题
  7. SQl常用语句总结(持续更新……)
  8. 1.7 编程基础之字符串 14 大小写字母互换 python
  9. remote: 认证失败,请确认您输入了正确的账号密码。 fatal: Authentication failed
  10. 彻底征服 Entity Framework Core 优化!
  11. java 查找引用_java – Eclipse查找方法的引用
  12. java script应用领域_JavaScript的应用
  13. 前端jquery学习
  14. 敏捷开发案例:用白板解决项目管理和团队沟通
  15. Interesting Housing Problem HDU - 2426 (KM)
  16. Mac 输入法原文件的安装位置
  17. Excel中的相对引用和绝对引用详解
  18. 【git commit --amend 修改提交记录】
  19. Python计算最大回撤、回撤天数
  20. Elasticsearch:从零开始到搜索 - 使用 Elasticsearch 摄取管道玩转你的数据

热门文章

  1. python入门之字符串
  2. Activity 的介绍和使用(一)
  3. 凌波微步-set的运用(去重)
  4. 知乎 鸿蒙目前只是安卓移植,[转载]转载:华为鸿蒙,一个本属于2025年的产品...
  5. H5在微信中获取openid
  6. CentOS使用(一)-----各种环境搭建
  7. “网络小偷”闯进无人超市 购物尝鲜要捂紧“钱包” 无人运营模式潜藏安全风险 或导致个人信息被窃取...
  8. 备胎的自我修养 |(3) 由零开始(下)
  9. nba里面啥是买断合同
  10. 简单的爬虫 从营养健康网爬取食物热量和营养成分等信息