Java 使用 poi 和 aspose 实现 word 模板数据写入并转换 pdf 增加水印
本项目所有源码和依赖资源都在文章顶部链接,有需要可以下载使用
1. 需求描述
- 从指定位置读取一个 word 模板
- 获取业务数据并写入该 word 模板,生成新的 word 文档
- 将新生成的 word 文档转换为 pdf 格式
- 对 pdf 文档添加水印
2. 效果预览
- word 模板
- 带水印的 pdf 文档
3. 实现思路
- word 模板数据写入:使用
poi-tl
库实现 - word 转 pdf 格式:
aspose-words
库实现 - pdf 增加水印:
aspose-pdf
库实现
4. 实现过程
4.1 依赖库准备
poi-tl
可以使用 maven 直接从中央仓库下载,但是 aspose
无法下载,需要从网上下载 jar 包并导入本地仓库
-
poi-tl
<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version></dependency>
-
aspose-word
将 jar 包导入本地仓库mvn install:install-file \-DgroupId="com.aspose" \-DartifactId="aspose-words" \-Dversion="15.8.0" \-Dpackaging="jar" \-Dfile="aspose-words-15.8.0-jdk16.jar"
项目中添加依赖
<dependency><groupId>com.aspose</groupId><artifactId>aspose-words</artifactId><version>15.8.0</version></dependency>
-
aspose-pdf
将 jar 包导入本地仓库mvn install:install-file \-DgroupId="com.aspose" \-DartifactId="aspose-pdf" \-Dversion="17.8" \-Dpackaging="jar" \-Dfile="aspose.pdf-17.8.jar"
项目中添加依赖
<dependency><groupId>com.aspose</groupId><artifactId>aspose-pdf</artifactId><version>17.8</version></dependency>
-
license.xml
由于aspose
库分为免费版和收费版,免费版导出的文档带有试用水印,所以需要添加license.xml
,版权关系不在文章中写出,有需要的可以下载文章顶部链接的完整源码包。
4.2 核心实现方法
@SpringBootApplication
public class Word2PDFApplication {public static void main(String[] args) {SpringApplication.run(Word2PDFApplication.class, args);// word 模板String wordTemplatePath = "src/main/resources/templates/简历模板.docx";// 写入数据后的 wordString wordOutputPath = "src/main/resources/templates/简历模板-output.docx";// word 转换为 pdfString pdfOutputPath = "src/main/resources/templates/简历模板.pdf";// pdf 增加水印String pdfWithMarkerOutputPath = "src/main/resources/templates/简历模板-marker.pdf";// step 1: 封装模板数据Map<String, Object> dataMap = getPersonDataMap();// step 2: 将数据写入 word 模板writeDataToWord(dataMap, wordTemplatePath, wordOutputPath);// step 3: 将 word 转换为 pdfconvertWordToPdf(wordOutputPath, pdfOutputPath);// step 4: 将 pdf 增加水印addMarkerToPdf(pdfOutputPath, pdfWithMarkerOutputPath);}// 封装业务数据,用于填入模板对应占位符中private static Map<String, Object> getPersonDataMap() {Map<String, Object> personDataMap = new HashMap<>();personDataMap.put("name", "张三");personDataMap.put("sex", "男");personDataMap.put("birthDate", "1998-12-02");personDataMap.put("id", "420202199812020011");personDataMap.put("phone", "18819297766");personDataMap.put("skills", "java Spring MySQL ...");return personDataMap;}// 将业务数据写入 word 模板,并生成新的 word 文件private static void writeDataToWord(Map<String, Object> dataMap, String wordTemplatePath, String wordOutputPath) {XWPFTemplate render = XWPFTemplate.compile(wordTemplatePath).render(dataMap);File dest = new File(wordOutputPath);if (!dest.getParentFile().exists()) {dest.getParentFile().mkdirs();}try {render.writeToFile(wordOutputPath);} catch (IOException e) {throw new RuntimeException(e);}}// 将新生成的带有业务数据的 word 文档转换为 pdf 格式private static void convertWordToPdf(String wordOutputPath, String pdfOutputPath) {// 验证 License 若不验证则转化出的 pdf 文档带有水印if (!getAsposeWordLicense()) {return;}FileOutputStream os = null;try {long old = System.currentTimeMillis();File file = new File(pdfOutputPath);os = new FileOutputStream(file);Document doc = new Document(wordOutputPath);doc.save(os, SaveFormat.PDF);long now = System.currentTimeMillis();System.out.println("pdf转换成功,共耗时:" + ((now - old) / 1000.0) + "秒");} catch (Exception e) {e.printStackTrace();} finally {if (os != null) {try {os.flush();os.close();} catch (IOException e) {e.printStackTrace();}}}}// 对转换后的 pdf 文档添加水印效果private static void addMarkerToPdf(String pdfOutputPath, String pdfWithMarkerOutputPath) {// 验证 License 若不验证则增加水印后的 pdf 文档带有试用水印boolean asposePdfLicense = getAsposePdfLicense();if (!asposePdfLicense) {return;}com.aspose.pdf.Document pdfDocument = new com.aspose.pdf.Document(pdfOutputPath);TextStamp textStamp = new TextStamp("水印文本");textStamp.getTextState().setFontSize(14.0F);textStamp.getTextState().setFontStyle(FontStyles.Bold);textStamp.setRotateAngle(45);textStamp.setOpacity(0.2);// 设置水印间距float xOffset = 100;float yOffset = 100;// 添加水印到每一页for (Page page : pdfDocument.getPages()) {float xPosition = 0;float yPosition = 0;// 在页面上添加水印直到页面被覆盖while (yPosition < page.getRect().getHeight()) {textStamp.setXIndent(xPosition);textStamp.setYIndent(yPosition);page.addStamp(textStamp);xPosition += xOffset;// 如果水印超过页面宽度,移到下一行if (xPosition + textStamp.getWidth() > page.getRect().getWidth()) {xPosition = 0;yPosition += yOffset;}}}// 保存修改后的文档pdfDocument.save(pdfWithMarkerOutputPath);}// 验证 license,否则有试用水印private static boolean getAsposeWordLicense() {boolean result = false;InputStream is = null;try {ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();org.springframework.core.io.Resource[] resources = resolver.getResources("classpath:license.xml");is = resources[0].getInputStream();License asposeLic = new License();asposeLic.setLicense(is);result = true;} catch (Exception e) {e.printStackTrace();} finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}return result;}// 验证 license,否则有试用水印private static boolean getAsposePdfLicense() {boolean result = false;InputStream is = null;try {ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();org.springframework.core.io.Resource[] resources = resolver.getResources("classpath:license.xml");is = resources[0].getInputStream();com.aspose.pdf.License asposeLic = new com.aspose.pdf.License();asposeLic.setLicense(is);result = true;} catch (Exception e) {e.printStackTrace();} finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}return result;}
}
相关文章:

Java 使用 poi 和 aspose 实现 word 模板数据写入并转换 pdf 增加水印
本项目所有源码和依赖资源都在文章顶部链接,有需要可以下载使用 1. 需求描述 从指定位置读取一个 word 模板获取业务数据并写入该 word 模板,生成新的 word 文档将新生成的 word 文档转换为 pdf 格式对 pdf 文档添加水印 2. 效果预览 word 模板 带水印的…...

Spring Boot进阶(93):体验式教程:手把手教你整合Spring Boot和Zipkin
📣前言 分布式系统开发中,服务治理是一个比较重要的问题。为了更好地实现服务治理,需要解决服务跟踪问题,即如何对分布式系统中的服务进行监控和追踪。本文将介绍如何使用Zipkin进行服务跟踪,并结合Spring Boot进行整合…...

Lvs +keepalivede : 高可用集群
keepalived为Ivs应运而生的高可用服务。Ivs的调度器无法做高可用,于是keepalived这个软件。 实现的是调度器的高可用。 但是: keepalived不是专为Ivs集群服务的,也可以做其他代理服务器的高可用。 lvs的高可用集群:主调度器和备调度器&…...

得物 Redis 设计与实践yu
一、前言 自建 Redis 系统是得物 DBA 团队自研高性能分布式 KV 缓存系统,目前管理的 ECS 内存总容量超过数十TB,数百多个 Redis 缓存集群实例,数万多个 Redis 数据节点,其中内存规格超过 1T 的大容量集群多个。 自建 Redis 系统采…...

优咔科技创新连接方案助力高质量5G车联服务
上海优咔网络科技有限公司 CEO 闫楠 【摘要】本文就智能网联汽车对高质量5G车联服务的需求背景和行业趋势进行了分析,主要介绍采用5G双SIM卡的创新连接方案,重点讲述双SIM卡联网的端到端体系架构和技术方案,并就优咔科技全方位支撑行业领先车…...

(a /b)*c的值
系列文章目录 进阶的卡莎C++_睡觉觉觉得的博客-CSDN博客数1的个数_睡觉觉觉得的博客-CSDN博客双精度浮点数的输入输出_睡觉觉觉得的博客-CSDN博客足球联赛积分_睡觉觉觉得的博客-CSDN博客大减价(一级)_睡觉觉觉得的博客-CSDN博客小写字母的判断_睡觉觉觉得的博客-CSDN博客纸币(…...
Hive 常用DML操作
本专栏案例数据集链接: https://download.csdn.net/download/shangjg03/88478038 1.加载文件数据到表 1.1 语法 LOAD DATA [LOCAL] INPATH filepath [OVERWRITE] INTO TABLE</...

centos部署tomcat
Java Downloads | Oracle 上面是下载网址 Tomcat是由Apache开发的一个Servlet容器,实现了对Servlet和JSP的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台,安全域管理和Tomcat阀 简单来说:Tomcat…...
【Spark】配置参数关系-重要
并行度数量 并行度指所有Executor可以同时执行的Task数, 每个Executor中的一个Core(线程,虚拟核数)同时只能执行一个Task, 所以 最大并行度 Executor数量 * 每个Executor的Core数; eg:资源配…...
[Qt之“MMM dd yyyyhh:mm:ss“]时间格式
这是时间格式字符串,用于表示日期和时间的显示格式。具体解释如下: “MMM”:表示月份的缩写,例如Jan、Feb、Mar等。“dd”:表示日期的两位数,例如01、02、03等。“yyyy”:表示年份的四位数&…...

SSM宾馆客房管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目
一、源码特点 SSM 宾馆客房管理系统是一套完善的信息系统,结合springboot框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代 码和数据库,系统…...
永远在路上
今年的1024是自己过的第八个程序员节,虽然没有放假,但是公司给每一个程序员都发了一个水果拼盘的福利,礼轻情意重吧!毕竟有许多公司都欠薪的情况下,我们公司不仅按时发薪资,而且还有固定福利和节日福利&…...
JS递归函数详解
递归函数是一种在函数内部调用自身的编程技巧。通过不断地将问题分解为更小的子问题,递归函数可以处理复杂的任务,并提供简洁和可读性高的代码实现。 基本原理: 1.递归函数由两个主要部分组成:基准条件(base case&…...

JS问题:如何实现文本一键复制和长按复制功能?
前端功能问题系列文章,点击上方合集↑ 序言 大家好,我是大澈! 本文约2000字,整篇阅读大约需要4分钟。 本文主要内容分三部分,第一部分是需求分析,第二部分是实现步骤,第三部分是问题详解。 …...

react实现步进器
创建一个步进器组件,包含当前步骤(currentStep)的状态以及前进和后退的操作: import React, { useState } from react;function Stepper() {const [currentStep, setCurrentStep] useState(1);const handleNext () > {setCu…...

【jenkins】centos7在线安装jenkins
一、系统要求 最低推荐配置 256MB可用内存 1GB可用磁盘空间(作为一个Docker容器运行jenkins的话推荐10GB) 软件配置 Java 8—无论是Java运行时环境(JRE)还是Java开发工具包(JDK)都可以 二、安装jenkins 准备一台安装有ce…...
Hive常用DDL操作
本专栏案例数据集链接: https://download.csdn.net/download/shangjg03/88478038 1. Database 1.1 查看数据库列表 show databases; 1.2 使用数据库 USE database_name;...
关于css中设置变量用于全局Css或者Js中使用
一、配置变量css文件 src/styles/variables.scss // 设置色值变量// 1、继承body中设置的样式内嵌style"--baseColor:#0075FF;" // 一般常用于Saas系统,如qiankun框架主应用决定子应用的样式 $primary: var(--baseColor, #0075FF); // 主色调࿰…...

Elasticsearch(十五)搜索---搜索匹配功能⑥--基于地理位置查询
一、前言 随着互联网的热门,越来越多的传统行业将全部或者部分业务转移到互联网上,其中不乏一些和地理位置强相关的行业。基于地理位置的搜索功能,大大提升了人们的生活和工作效率。例如,外出旅行时,只需要用手机打开…...
为什么axios会有params和data两个参数
不知道大家有没有过这种感觉,突然一个问题百思不得其解,然后突然有一天就明白了。然后就感觉这个问题原来这么简单,本来想记录下来,但是又感觉这么简单的问题记录下来没啥意义。但是回过头来想一想,这个问题之前其实困…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...

mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...

图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...