掌握iText:轻松处理PDF文档-高级篇-添加水印


前言
iText作为一个功能强大、灵活且广泛应用的PDF处理工具,在实际项目中发挥着重要作用。通过这些文章,读者可以深入了解如何利用iText进行PDF的创建、编辑、加密和提取文本等操作,为日常开发工作提供了宝贵的参考和指导。
掌握iText:轻松处理PDF文档-基础篇
掌握iText:轻松处理PDF文档-进阶篇
需求描述
可能你会经常遇到类似的场景, 为了保护敏感信息和版权,需要在PDF文件上添加水印,在类似这样的需求上再作一个延伸,可能就是两种情况:第一种,程序在处理数据后,生成新的pdf文档的同时增加水印;第二种,pdf文档已经存在,需要在导出的时候,给已经存在的pdf文档增加水印。那么这两种需求,如果使用iText5,应该怎么实现呢?
iText的依赖
在maven的pom.xml中配置:
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.3</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version>
</dependency>
生成新的pdf文档的同时增加水印
程序在处理数据后,生成新的pdf文档的同时增加水印,具体的步骤如下:
1.创建一个大小为A4纸、横向显示的PDF文档。
2.创建PdfWriter对象,用于将文档内容写入到PDF文件中。
3.打开文档。
4.创建第一页(可省略)。
5.获取水印的PdfContentByte对象。
6.调用setWaterMar方法,在水印画布上设置水印内容和样式。
7.循环100次,在文档中添加一段文字。
8.关闭文档和PdfWriter对象。
9.输出成功生成PDF文件的消息。
其中 setWaterMar 方法封装了具体的水印设置逻辑,具体逻辑如下:
1.检查水印画布是否为空。
2.开始设置水印文本。
3.设置水印的透明度。
4.创建PdfGState对象,设置填充字体的不透明度为0.4f。
5.设置水印的字体和大小。
6.设置水印的对齐方式、位置和旋转角度。
7.设置水印的颜色。
8.结束设置水印文本。
// 往pdf文档中写入文本内容时,添加水印
@Test
public void test() throws FileNotFoundException, DocumentException {//实现A4纸页面 并且横向显示(不设置则为纵向)Document document = new Document(PageSize.A4.rotate());PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream("e:/pdf-test/test-v1.pdf"));// 打开文档document.open();// 创建第一页(如果只有一页的话,这一步可以省略)document.newPage();// 加入水印,水印内容:x+y=zPdfContentByte waterMar = pdfWriter.getDirectContentUnder();this.setWaterMar(waterMar, "x+y=z");for (int i = 0; i < 100; i++) {// 加入文档内容document.add(new Paragraph("my first pdf demo"));}// 关闭文档document.close();pdfWriter.close();
}
private void setWaterMar(PdfContentByte waterMar, String waterContent) {if (waterMar == null) {return;}// 开始设置水印waterMar.beginText();// 设置水印透明度PdfGState gs = new PdfGState();// 设置填充字体不透明度为0.4fgs.setFillOpacity(0.4f);try {// 设置水印字体参数及大小(字体参数,字体编码格式,是否将字体信息嵌入到pdf中(一般不需要嵌入),字体大小)waterMar.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED), 60);// 设置透明度waterMar.setGState(gs);// 设置水印对齐方式 水印内容 X坐标 Y坐标 旋转角度waterMar.showTextAligned(Element.ALIGN_RIGHT, waterContent, 500, 430, 45);// 设置水印颜色waterMar.setColorFill(BaseColor.GRAY);//结束设置waterMar.endText();waterMar.stroke();} catch (IOException e) {e.printStackTrace();} catch (DocumentException e) {throw new RuntimeException(e);}
}
效果如下:

给已经生成的pdf文档增加水印
1.指定输入和输出的 PDF 文件路径。
2.创建 PdfReader 对象,用于读取原始 PDF 文件。
3.创建 PdfStamper 对象,用于添加水印,并传入原始 PDF 文件和输出 PDF 文件的路径。
4.获取原始 PDF 文件的页数。
5.加载自定义字体 HongLeiXingShuJianTi-2.otf。我这里是从字体天下网(https://www.fonts.net.cn)下载一个字体,可以使用你拥有的其他字体,需要注意字体版权问题,我下载这个是商用免费。
6.设置水印的字体大小和旋转角度。
7.准备向每一页添加水印。
8.循环迭代每一页,获取当前页的 PdfContentByte 对象,即用于绘制内容的画布。
9.调用 setWaterMar 方法,在当前页的画布上添加水印。
10.关闭 PdfStamper 和 PdfReader 对象,释放资源。
11.输出一条成功添加水印的消息。
其中 setWaterMar 方法封装了具体的水印设置逻辑,具体逻辑如下:
1.设置水印的填充颜色为浅灰色。
2.开始绘制文本。
3.设置文本的字体和大小。
4.使用嵌套循环,将水印文本重复添加到当前页的多个位置上。
5.结束绘制文本。
@Test
public void test2() {try {// 输入PDF文件路径String inputFile = "e:/pdf-test/test.pdf";// 输出PDF文件路径String outputFile = "e:/pdf-test/test-v2.pdf";// 创建PdfReader对象读取原始PDF文件PdfReader reader = new PdfReader(inputFile);// 创建PdfStamper对象,用于添加水印PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));// 设置水印属性int n = reader.getNumberOfPages();URL resource = getClass().getClassLoader().getResource("HongLeiXingShuJianTi-2.otf");FontFactory.register(resource.getPath(), "HongLeiXingShuJianTi-2.otf");BaseFont baseFont = BaseFont.createFont("HongLeiXingShuJianTi-2.otf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);float fontSize = 20; // 设置字体大小float watermarkAngle = 10; // 设置水印旋转角度PdfContentByte watermark;// 添加水印到每一页for (int i = 1; i <= n; i++) {watermark = stamper.getOverContent(i);this.setWaterMar(watermark, "凡夫编程", baseFont, fontSize, watermarkAngle);}// 关闭PdfStamper和PdfReader对象stamper.close();reader.close();System.out.println("水印已添加到PDF文档中。");} catch (DocumentException | IOException e) {e.printStackTrace();}
}
private void setWaterMar(PdfContentByte watermark, String waterContent, BaseFont baseFont, float fontSize, float watermarkAngle) {watermark.setColorFill(BaseColor.LIGHT_GRAY);watermark.beginText();watermark.setFontAndSize(baseFont, fontSize);for (int m = 0; m < 10; m++) {for (int n = 0; n < 10; n++) {watermark.showTextAligned(Element.ALIGN_LEFT, "凡夫编程", 10 + m * 150, 10 + n * 100, watermarkAngle);}}watermark.endText();
}
效果如下:

写入与读取元数据
写入元数据:
1.创建一个空白的PDF文档对象。
2.创建PdfWriter对象,用于将文档内容写入到PDF文件中,并指定输出文件路径。
3.打开文档。
4.向文档中添加一段文字内容。
5.使用addCreator方法设置文档的创建者信息。
6.使用addTitle方法设置文档的标题信息。
7.使用addAuthor方法设置文档的作者信息。
8.关闭文档。
@Test
public void test6() {Document document = new Document();try {// 设置加密算法和用户/所有者密码PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("e:/pdf-test/test-v6.pdf"));document.open();// 添加一些内容到文档中document.add(new Paragraph("This is pdf document."));document.addCreator("fanfu");document.addTitle("test-pdf");document.addAuthor("gaoxing");document.close();} catch (DocumentException | IOException e) {e.printStackTrace();}
}
读取元数据:
1.创建一个PdfReader对象,用于读取指定PDF文件("e:/pdf-test/test-v6.pdf")的内容。
2.调用getInfo方法获取PDF文档的元数据信息,并将其存储在一个HashMap对象中。
3.使用for循环遍历HashMap中的键值对,打印每个键对应的值。
@Test
public void test7() {try {// 设置加密算法和用户/所有者密码PdfReader pdfReader = new PdfReader(new FileInputStream("e:/pdf-test/test-v6.pdf"));HashMap<String, String> info = pdfReader.getInfo();for (String key : info.keySet()) {System.out.println(info.get(key));}} catch (IOException e) {e.printStackTrace();}
}
相关文章:
掌握iText:轻松处理PDF文档-高级篇-添加水印
前言 iText作为一个功能强大、灵活且广泛应用的PDF处理工具,在实际项目中发挥着重要作用。通过这些文章,读者可以深入了解如何利用iText进行PDF的创建、编辑、加密和提取文本等操作,为日常开发工作提供了宝贵的参考和指导。 掌握iText&…...
深度学习基本概念
1.全连接层 全连接层就是该层的所有节点与输入节点全部相连,如图所 示。假设输入节点为X1, X 2, X 3,输出节点为 Y 1, Y 2, Y 3, Y 4。令 矩阵 W 代表全连接层的权重, W 12也就代表 …...
2023年最详细的:本地Linux服务器安装宝塔面板,并内网穿透实现公网远程登录
📚📚 🏅我是默,一个在CSDN分享笔记的博主。📚📚 🌟在这里,我要推荐给大家我的专栏《Linux》。🎯🎯 🚀无论你是编程小白,还是有一…...
基于ssm金旗帜文化培训学校网站的设计与开发论文
摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对培训学校展示信息管理混乱,出错率高,信息安全…...
【Java】猜数字小游戏
规则 游戏开始随机生成4位数字符串,每个数字从0到9各不相同,比如0123玩家10次猜数机会,输入4位数字符串,每个数字从0到9各不相同游戏判断玩家输入与所猜谜底数,给出结果nAnB,A表示位置和数字都猜对的个数&…...
汽车EDI:Chrysler EDI项目案例
菲亚特克莱斯勒汽车Fiat Chrysler Automobiles(FCA)是一家全球性汽车制造商,主营产品包括轿车、SUV、皮卡车、商用车和豪华车等多种车型。其旗下品牌包括菲亚特、克莱斯勒、道奇、Jeep、Ram、阿尔法罗密欧和玛莎拉蒂等。 Chrysler通过EDI来优化订单处理、交付通知、…...
Locust:可能是一款最被低估的压测工具
01、Locust介绍 开源性能测试工具https://www.locust.io/,基于Python的性能压测工具,使用Python代码来定义用户行为,模拟百万计的并发用户访问。每个测试用户的行为由您定义,并且通过Web UI实时监控聚集过程。 压力发生器作为性能…...
用23种设计模式打造一个cocos creator的游戏框架----(十八)责任链模式
1、模式标准 模式名称:责任链模式 模式分类:行为型 模式意图:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处…...
100天精通风控建模(原理+Python实现)——第9天:风控建模中为什么需要特征工程?
风控模型已在各大银行和公司都实际运用于业务,用于营销和风险控制等。本文以视频的形式阐述风控建模中为什么需要特征工程。并提供风控建模原理和Python实现文章清单。 之前已经阐述了100天精通风控建模(原理+Python实现)——第1天:什么是风控建模? 100天精通风控…...
【PHP】计算某个特定时间戳距离现在的天数
在PHP中,你可以使用time()函数获取当前时间的时间戳,然后将它与你想要计算的过去或未来的时间戳进行比较。为了得到相差的天数,你需要先用两个时间戳相减得到秒数差,然后再除以一天的总秒数(通常是86400秒)…...
lv12 uboot移植深化 9
u-boot-2013.01移植 【实验目的】 了解u-boot 的代码结构及移植的基本方法 【实验环境】 ubuntu 14.04发行版FS4412实验平台交叉编译工具arm-none-linux-gnueabi- 【注意事项】 实验步骤中以“$”开头的命令表示在 ubuntu 环境下执行 【实验步骤】 1 建立自己的平台 1.…...
大数据与深度挖掘:如何在数字营销中与研究互动
数字营销最吸引人的部分之一是对数据的内在关注。 如果一种策略往往有积极的数据,那么它就更容易采用。同样,如果一种策略尚未得到证实,则很难获得支持进行测试。 数字营销人员建立数据信心的主要方式是通过研究。这些研究通常分为两类&…...
xtu oj 1327 字符矩阵
按照示例的规律输出字符矩阵。 比如输入字母D时,输出字符矩阵如下 ABCDCBA BBCDCBB CCCDCCC DDDDDDD CCCDCCC BBCDCBB ABCDCBA字符矩阵行首、尾都无空格。 输入 每行一个大写英文字母,如果字符为#,表示输入结束,不需要处理。 …...
讨论用于评估DREX的五种DR指标
概要 动态范围是已经使用了近一个世纪的用于评估接收机性能的参数。这里介绍五种动态有关指标的定义及测试方法,用于评估数字接收激励器(DREX,digital receiver exciters)。DREX是构成雷达的关键整部件,其瞬时带宽&am…...
基于SpringBoot的在线疫苗预防小程序
文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的在线疫苗预防小程序,ja…...
Kafka使用总结
1、Kafka是何如做到高性能的? a、消息批处理减少网络通信开销,提升系统吞吐能力(先攒一波,消息以“批”为单位进行处理) 生产端:无论是同步发送还是异步发送,Kafka都不会立即就把这条消息发送出…...
2023 年山东省职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题
2023 年山东省职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题 目录 任务 1 网络平台搭建(50 分) 任务 2 网络安全设备配置与防护(250 分) 模块二 网络安全事件响应、数字取证调查、应用程序安…...
Apache Web 服务器监控工具
将Apache Web 服务器监控纳入 IT 基础架构管理策略有助于先发制人地识别性能瓶颈,这种主动监控方法提供必要的数据,以确保 Web 服务器能够胜任任务,并在需要时进行优化。保证客户获得流畅、无忧的用户体验可以大大有助于巩固他们对组织的信任…...
MySQL执行语句 Table ‘mysql.servers‘ doesn‘t exist
执行语句报错: mysql> flush privileges; ERROR 1146 (42S02): Table mysql.servers doesnt exist解决: 进入数据库 删除servers表 mysql> use mysql Database changed mysql> drop table if exists servers; Query OK, 0 rows affected, …...
在datagridview列显示下拉操作
DataGridViewComboBoxExColumn 设定好类型 需要设置的地方是: 绑定数据的操作: 因为此处绑定数据实际为数据 参数 显示的操作,不影响datasource的数据绑定 下一步 数据绑定: DGVCOrderZhuangtai.ValueType typeof(EOrderZhuan…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
