freemark 模板生成doc文件,此doc文件为xml格式,无法直接转pdf

需要doc转docx文件,才能转pdf

方法1:docx4j 转 pdf

方法2: e-iceblue docx 转 pdf、xml-doc 转 pdf

打包方式,需要本地引入jar包,下载后,将lib里的jar包放入项目中

Free Spire.Doc for Java | 100% 免费 Java Word 组件

pom文件引入 ${project.basedir} 是系统变量,代表本目录,build配置是打包时,将本地文件加入项目

<dependency><groupId>e-iceblue</groupId><artifactId>spire.pdf</artifactId><version>5.2.0</version><scope>system</scope><systemPath>${project.basedir}/src/main/resources/lib/Spire.Doc.jar</systemPath></dependency><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includeSystemScope>true</includeSystemScope></configuration></plugin></plugins></build>

​​​​​​​

方法3:poi (可以自己搜教程)

依赖

<!-- iText pdf 依赖--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf-itext5</artifactId><version>9.1.5</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version><scope>compile</scope></dependency><!-- docx 依赖 导出pdf --><dependency><groupId>org.docx4j</groupId><artifactId>docx4j</artifactId><version>6.1.2</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.docx4j</groupId><artifactId>docx4j-export-fo</artifactId><version>6.0.0</version></dependency><!-- e-iceblue 导出pdf --><dependency><groupId>e-iceblue</groupId><artifactId>spire.doc.free</artifactId><version>5.2.0</version></dependency>
<repositories><repository><id>public</id><name>阿里云公共仓库</name><url>https://maven.aliyun.com/repository/public/</url><releases><enabled>true</enabled></releases></repository><repository><id>com.e-iceblue</id><url>https://repo.e-iceblue.cn/repository/maven-public/</url></repository></repositories>
/*** @Author: LiSaiHang* @Date: 2023/4/23 3:26 下午*/
@RestController
@RequestMapping("/module/documents")
@Slf4j
public class FreeMarkController {@GetMapping("/generate")public void doc(HttpServletResponse response) {Map<String, Object> dataMap = new HashMap<>();///姓名dataMap.put("name", "张三");dataMap.put("phone", "15532123328");dataMap.put("idCard", "130429199711113617");dataMap.put("sex", "男");String result = "";String docName = System.currentTimeMillis() + (int) (Math.random() * 90000 + 10000) + ".doc";String pdfName = System.currentTimeMillis() + (int) (Math.random() * 90000 + 10000) + ".pdf";response.setHeader("content-Type", "application/octet-stream");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + pdfName);// 下载输出流ServletOutputStream outputStream = null;// doc文件输出流InputStream inputStream = null;// pdf文件输出流ByteArrayOutputStream fileOutputStream = null;try {// 获取渲染数据result = FreeMarkUtils.freemarkerRender(dataMap, "test.doc");inputStream = new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8));// 生成 doc 文件FileUtils.copyInputStreamToFile(inputStream, new File(docName));// doc 文件转docx文件final String docxFile = this.docToDocx(docName);// 方法1:docx文件转pdf文件// this.docx4jWordToPdf(docxFile, pdfName);// 方法2:docx文件转pdf文件// com.spire.doc.Document 实例化Document类的对象Document doc = new Document();// 加载Worddoc.loadFromFile(docxFile);// 保存为PDF格式 com.spire.doc.FileFormatdoc.saveToFile(pdfName, FileFormat.PDF);// pdf 缩放设置pdfPageSetting(pdfName);// 获取文件输出流fileOutputStream = FreeMarkUtils.getFileOutputStream(new File(pdfName));// 设置文件名outputStream = response.getOutputStream();outputStream.write(fileOutputStream.toByteArray());} catch (Exception e) {e.printStackTrace();} finally {try {if (outputStream != null) {outputStream.close();}if (fileOutputStream != null) {fileOutputStream.close();}if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}}/*** doc转docx* @param docPath doc文件路径* @return*/private String docToDocx(String docPath) {String docxPath = docPath.replaceAll("(\\.docx)|(\\.doc)", ".docx");try (FileInputStream inputStream = new FileInputStream(docPath);) {WordprocessingMLPackage wmlPackage = Docx4J.load(inputStream);//转换为DOCXtry (FileOutputStream docx = new FileOutputStream(docxPath);) {Docx4J.save(wmlPackage, docx, Docx4J.FLAG_SAVE_ZIP_FILE);docPath = docxPath;}} catch (Exception e) {System.out.println((docPath + ":不需要转换:" + e.getLocalizedMessage()));}return docPath;}/*** 通过docx4j 实现word转pdf** @param sourcePath 源文件地址 如 /root/example.doc* @param targetPath 目标文件地址 如 /root/example.pdf*/public String docx4jWordToPdf(String sourcePath, String targetPath) {try {WordprocessingMLPackage pkg = Docx4J.load(new File(sourcePath));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("FangSong"));fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));fontMapper.put("等线", PhysicalFonts.get("SimSun"));fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));fontMapper.put("新細明體", PhysicalFonts.get("SimSun"));PhysicalFonts.addPhysicalFonts("SimSun", WordUtils.class.getResource("/simsun.ttc"));pkg.setFontMapper(fontMapper);Docx4J.toPDF(pkg, new FileOutputStream(targetPath));} catch (Exception e) {log.error("[docx4j] word转pdf失败:{}", e.toString());}return targetPath;}/*** 对pdf页面设置,缩放比例设置* @param pdfName pdf文件名称*/private void pdfPageSetting(String pdfName) {//创建PdfDocument实例PdfDocument originalDoc = new PdfDocument();//加载PDF文件originalDoc.loadFromFile(pdfName);//创建一个新的PdfDocument实例PdfDocument newDoc = new PdfDocument();//遍历所有PDF 页面for (int i = 0; i < originalDoc.getPages().getCount(); i++) {PdfPageBase page = originalDoc.getPages().get(i);//设置新文档的页边距为10PdfMargins margins = new PdfMargins(10);//设置新文档的页面大小为A2PdfPageBase newPage = newDoc.getPages().add(PdfPageSize.A2, margins);//调整画布,设置内容也根据页面的大小进行缩放double wScale = (PdfPageSize.A2.getWidth() - 20) /         PdfPageSize.A4.getWidth();double hScale = (PdfPageSize.A2.getHeight() - 20) / PdfPageSize.A4.getHeight();newPage.getCanvas().scaleTransform(wScale, hScale);//复制原文档的内容到新文档newPage.getCanvas().drawTemplate(page.createTemplate(), new Point2D.Float());}//保存PDFnewDoc.saveToFile(pdfName);}
}

工具类

package com.dpxdata.framework.common.utils;import com.itextpdf.text.*;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.ui.freemarker.SpringTemplateLoader;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;import java.io.*;
import java.util.Map;/*** @Description: pdf 导出工具类* @Author: LiSaiHang* @Date: 2022/1/7 11:30 上午*/
@Component
@Slf4j
public class FreeMarkUtils {private FreeMarkUtils() {}private volatile static Configuration configuration;static {if (configuration == null) {synchronized (FreeMarkUtils.class) {if (configuration == null) {configuration = new Configuration(Configuration.VERSION_2_3_28);}}}}/*** freemarker 引擎渲染 html** @param dataMap  传入 html 模板的 Map 数据* @param fileName 模板文件名称*                 eg: "templates/template.ftl"* @return*/public static String freemarkerRender(Map<String, Object> dataMap, String fileName) {configuration.setDefaultEncoding("UTF-8");configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);try {// TODO Jar包运行时,是无法读取classpath下资源文件,可以通过 SpringTemplateLoader 读取资源文件目录// 本地运行时,可以通过本地文件流读取资源文件final SpringTemplateLoader templateLoader = new SpringTemplateLoader(new DefaultResourceLoader(), "classpath:templates");configuration.setTemplateLoader(templateLoader);// 服务器运行时,可以通过目录,获取文件流读取资源文件
//            configuration.setDirectoryForTemplateLoading(new File("/Users/lisaihang/Documents/"));configuration.setLogTemplateExceptions(false);configuration.setWrapUncheckedExceptions(true);Template template = configuration.getTemplate(fileName);log.info("填充模板动态数据");return FreeMarkerTemplateUtils.processTemplateIntoString(template, dataMap);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return null;}/*** 使用 iText 生成 PDF 文档** @param htmlTmpStr html 模板文件字符串* @param fontFile   所需字体文件(相对路径+文件名)*/public static byte[] createHtml2Pdf(String htmlTmpStr, String fontFile) {log.info("根据模板生成PDF文件");ByteArrayOutputStream outputStream = null;byte[] result = null;// 生成 字体临时文件// TODO jar包运行后,是无法直接读取 classpath 下的资源文件,需要通过文件流读取,生成临时文件final String tempFont = "simsun_temp_"+ ".ttc";File existFile = new File(tempFont);if (!existFile.exists()) {final File tempFile = getTempFile(fontFile, tempFont);existFile = tempFile;}// TODO jar包运行后,是无法直接读取 classpath 下的资源文件,需要通过文件流读取,生成临时文件try {outputStream = new ByteArrayOutputStream();ITextRenderer renderer = new ITextRenderer();renderer.setDocumentFromString(htmlTmpStr);ITextFontResolver fontResolver = renderer.getFontResolver();// 解决中文支持问题,需要所需字体(ttc)文件fontResolver.addFont(existFile.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);renderer.layout();renderer.createPDF(outputStream);// 对Html2Pdf 的文件插入水印图片final String fileName = System.currentTimeMillis() + (int) (Math.random() * 90000 + 10000) + ".pdf";addWaterMark(outputStream.toByteArray(), fileName);final ByteArrayOutputStream fileOutputStream = getFileOutputStream(new File(fileName));result = fileOutputStream.toByteArray();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (DocumentException e) {e.printStackTrace();} finally {try {if (outputStream != null) {outputStream.flush();outputStream.close();}
//                if (tempFile.exists()) {
//                    tempFile.delete();
//                }} catch (IOException e) {e.printStackTrace();}}return result;}/*** 文件转字节输出流** @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 {input.close();bytestream.close();log.info("删除临时文件");if (outFile.exists()) {outFile.delete();}} catch (IOException e) {e.printStackTrace();}}return bytestream;}/*** 获取资源文件的临时文件* 资源文件打jar包后,不能直接获取,需要通过流获取生成临时文件** @param fileName 文件路径 temp/temp.ftl* @return*/public static File getTempFile(String fileName, String tempFont) {final File tempFile = new File(tempFont);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("https://dpxdata.oss-cn-beijing.aliyuncs.com/upload/kbt/null_1660715685801.png");// 设置坐标 绝对位置 X Yimage.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;}
}

Freemark 模板生成doc文件,xml doc文件转docx 文件,docx文件转pdf文件相关推荐

  1. .tex类型文件怎么阅读_Python用于NLP :处理文本和PDF文件

    提示:代码图片可以点击全屏查看,双指操作还可以放大缩小. 这是我的Python用于自然语言处理(NLP)系列文章的第一篇文章.在本文中,我们将从Python for NLP的基础知识开始.我们将看到如 ...

  2. java利用Freemarker模板生成格式友好的doc或者docx文档

    之前写过一篇利用Freemarker模板生成doc的博客,不过那个博客有点缺陷,不支持生成docx格式的文档.所以,这里补充一篇,生成docx或doc格式的文档以具体的docx模板或者doc模板为主. ...

  3. ftl模板导出excel_使用freemark模板生成excel

    1.背景 文件操作中导入导出功能在项目中十分常见,这里我们要聊的是导出excel这一功能.老话题常谈常新,小编给大家介绍使用freemark模板的方式导出excel. 2.实现 Demo中采用spri ...

  4. 将HTML文件转换为PDF文件(Thymeleaf模板转换,简单解决中文问题, 解决HTML带图片转换PDF文件问题)

    将HTML文件转换为PDF文件 一.导入依赖 <!-- itext生成Pdf --> <dependency><groupId>com.itextpdf</g ...

  5. 压缩pdf文件,自行调节清晰度从而调节文件大小,切分pdf文件为多个小文件,控制每个文件大小

    前言 因为内网,不能发送大于10M的文件,无奈只能将pdf切分进行 压缩pdf文件,自行调节清晰度从而调节文件大小 import fitz import osdef covert2pic(zoom): ...

  6. 【PDF转换图片】如何把pdf文件转换成图片?如何把批量pdf文件转换成图片?如何把多目录批量pdf文件转换成图片?如何pdf文件转换成图片不失真不损失清晰度?今天教方法

    在工作中常常需要将PDF转换为图片,好多免费但是图片有水印和功能不全的问题. 还有市面上很多软件知识完成了部分的工作,比如只能单个文件转PDF,那么遇到多文件的就只能挨个转么? 还有转换的格式支持的非 ...

  7. python抓取网页数据没有文件输出什么原因_Python抓取网页内容并输出PDF文件

    环境:pytho3.5.1 import requests import os import time import random import re import pdfkit from bs4 i ...

  8. 1024程序员节|历经一个月总结使用java实现pdf文件的电子签字+盖章+防伪二维码+水印+PDF文件加密的全套解决方案

  9. java根据pdf模板生成指定格式的pdf文件

    java根据pdf模板生成指定格式的pdf文件 一.工具准备 事先得准备好Adobe Acrobat DC,这是一款专门编辑pdf的工具,小编已经给大家准备好了. 链接:https://pan.bai ...

最新文章

  1. php composer 无法下载,php – composer无法安装laravel / passport
  2. 《LeetCode力扣练习》第13题 C语言版 (做出来就行,别问我效率。。。。)
  3. java.lang.NullPointerException错误分析
  4. esp8266make相关文件改进
  5. JMeter 教程汇总链接
  6. python random randint_python中random.randint和random.randrange的区别详解
  7. Linux 如何创建新文件、修改文件权限、新文件读写 ?
  8. 自定义View----滑动刻度尺与流式布局 实例(四)
  9. TensorFlow 学习------第一天
  10. 浅析PCIe链路LTSSM状态机
  11. 计算机一级单元格填充,电脑Excel表格怎么对不连续的单元格进行批量填充
  12. 手机屏幕分辨率真的是越高越清晰吗?
  13. 软考中级嵌入式系统设计师备考攻略
  14. python 条件循环赋值_python学习(五) 条件、循环和其他语句
  15. Windows系统监控
  16. Fluent compiled 失败:UDF library you are trying to load (libudf) is not compiled for parallel on the
  17. Feign原理:current list of Servers哪里来的
  18. 基于JavaSwing开发天猫购物商城系统(用户 管理员角色) 课程设计 毕业设计源码
  19. mac添加Chrome插件的方法
  20. Windows使用SSH登录VM虚拟机

热门文章

  1. 隆重推介:胡光超老师2022年度优秀中高项学员代表龙虎榜!
  2. 架构系列——架构师必备基础:单体、分布式、集群与冗余的区别
  3. python 爬取直播弹幕视频_Python爬取b站任意up主所有视频弹幕
  4. Lite系列开发框架
  5. ActiveMQ的两种消息模式及实现代码
  6. matlab GUI 打包程序(Application Complier生成exe文件和App打包)
  7. 让所有GUI都自动化-PyAutoGUI(GUI自动化工具)
  8. Android app如何用手机调试
  9. Protostuff的使用
  10. Kettle--使用读取配置的方式连接数据库