当前位置: 首页 > news >正文

使用 iText 9 为 PDF 添加文字水印的完整实战

1️⃣ 背景与需求

在企业内部流转或对外发布的 PDF 文档中,往往需要加入“内部仅阅”“机密”等标识,以防止泄露或伪造。iText 9 作为业界成熟的 PDF 处理库,提供了灵活的绘图 API,能够在已有 PDF 上批量、透明、倾斜地绘制文字水印。

博客示例基于 iText 9,实现了以下功能:

  • 支持中文水印(使用 STSong-Light 字体)
  • 透明度可调(示例中为 0.2)
  • 文字倾斜 45°,实现斜纹平铺效果
  • 自动遍历所有页并在每页均匀分布水印

2️⃣ 环境准备

<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-core -->
<dependency><groupId>com.itextpdf</groupId><artifactId>itext-core</artifactId><version>9.3.0</version><type>pom</type>
</dependency><!-- https://mvnrepository.com/artifact/com.itextpdf/html2pdf -->
<dependency><groupId>com.itextpdf</groupId><artifactId>html2pdf</artifactId><version>6.2.1</version>
</dependency>

3️⃣ 关键代码剖析

3.1 创建 PDF 读取/写入流

PdfReader reader = new PdfReader(inputStream);
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
  • PdfReader 读取原始 PDF,PdfWriter 将结果写入内存流。
  • PdfDocument 同时持有读写能力,适合在原文件上直接添加内容。

3.2 配置中文字体

PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
  • STSong-Light 是 iText 自带的宋体变体,配合 UniGB-UCS2-H 编码即可渲染简体中文。

3.3 定义水印样式

Paragraph paragraph = new Paragraph(watermarkText).setFont(font).setFontSize(15).setFontColor(new DeviceRgb(200, 200, 200)).setOpacity(0.2f);
  • setOpacity 控制透明度,0.2 让底层文字仍可辨认。
  • 颜色使用浅灰,避免遮挡正文。

3.4 遍历页面并绘制水印

int numberOfPages = pdfDoc.getNumberOfPages();
for (int i = 1; i <= numberOfPages; i++) {PdfPage page = pdfDoc.getPage(i);Rectangle pageSize = page.getPageSize();PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(),page.getResources(), pdfDoc);Canvas canvas1 = new Canvas(canvas, pageSize);// 平铺参数float xSpacing = 300, ySpacing = 150;float xStart = 100, yStart = pageSize.getHeight() - 100;for (float y = yStart; y > 0; y -= ySpacing) {for (float x = xStart; x < pageSize.getWidth(); x += xSpacing) {canvas1.showTextAligned(paragraph, x, y, i,TextAlignment.CENTER,com.itextpdf.layout.properties.VerticalAlignment.MIDDLE,45);   // 45° 斜纹}}canvas1.close();
}
  • page.newContentStreamBefore() 在原内容之前写入,确保水印位于页面底层。
  • 双层循环实现 水平 300px、垂直 150px 的网格平铺。
  • showTextAligned 支持文字对齐、垂直居中以及旋转角度(45°),是 iText 9 推荐的文字绘制方式。

3.5 关闭文档并返回流

pdfDoc.close();
return new ByteArrayInputStream(outputStream.toByteArray());
  • 关闭 PdfDocument 会自动写入 EOF 标记,防止文件损坏。

4️⃣ 常见问题与最佳实践

场景建议说明
大文件(>100 MB)使用 PdfWriter 的 setSmartMode(true),开启智能写入,降低内存占用。iText 官方文档推荐的性能优化手段。
多语言水印通过 PdfFontFactory.createFont(“NotoSansCJKsc-Regular.otf”, PdfEncodings.IDENTITY_H) 加载支持多语言的 Unicode 字体。适用于中英混排。
水印位置不均调整 xStart、yStart 与间距参数,或使用页面宽高比例计算。不同页面尺寸(A4、Letter)需要自适应。
需要在已有水印上再添加使用 PdfCanvas 的 newContentStreamAfter() 在最上层绘制,避免被覆盖。参考 iText 9 的层次概念。

5️⃣ 小结

本文完整演示了 iText 9 为 PDF 添加中文文字水印的实现细节。核心要点包括:

  1. 正确加载中文字体
  2. 使用 Paragraph 配合透明度、颜色定义水印样式
  3. 通过 PdfCanvas + Canvas 在每页创建 平铺、倾斜 的文字网格
  4. 关闭文档确保 PDF 完整性

只要把上述工具类集成到项目中,即可在任何 Java 环境下快速实现批量水印功能,满足企业文档安全的基本需求。祝编码愉快!

6️⃣ 完整代码

import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.kernel.geom.Rectangle;
import org.apache.commons.lang3.StringUtils;import java.io.*;/*** @ClassName: FileWatermarkUtils* @Description: 文件水印工具类* @Author: Maxon Phong* @Date: 2025/10/10 9:50**/
public class FileWatermarkUtils {/*** PDF加水印** @param file          文件* @param watermarkText 水印文本* @return 添加水印后的PDF文件*/public static InputStream addWatermark2PDF(File file, String watermarkText) {try {return addWatermark2PDF(new FileInputStream(file), watermarkText);} catch (FileNotFoundException e) {throw new RuntimeException(e);}}/*** PDF加水印** @param inputStream   文件流* @param watermarkText 水印文本* @return 添加水印后的PDF文件流*/public static InputStream addWatermark2PDF(InputStream inputStream, String watermarkText) {if (null == inputStream) {throw new RuntimeException("输入文件不能为空");}if (null == watermarkText) {watermarkText = StringUtils.EMPTY;}try {// 创建输出流用于保存添加水印后的PDFByteArrayOutputStream outputStream = new ByteArrayOutputStream();// 创建PdfReader和PdfWriterPdfReader reader = new PdfReader(inputStream);PdfWriter writer = new PdfWriter(outputStream);// 创建PdfDocument对象PdfDocument pdfDoc = new PdfDocument(reader, writer);// 获取中文字体以支持中文水印PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");// 定义水印样式Paragraph paragraph = new Paragraph(watermarkText).setFont(font).setFontSize(15) // 设置字体大小为15.setFontColor(new DeviceRgb(200, 200, 200)).setOpacity(0.2f); // 设置透明度为0.2f// 遍历每一页添加水印int numberOfPages = pdfDoc.getNumberOfPages();for (int i = 1; i <= numberOfPages; i++) {PdfPage page = pdfDoc.getPage(i);Rectangle pageSize = page.getPageSize();// 在页面上添加水印PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);Canvas canvas1 = new Canvas(canvas, pageSize);// 计算水印的位置,实现平铺效果float xSpacing = 300; // 水平间距float ySpacing = 150; // 垂直间距float xStart = 100;   // 起始X位置float yStart = pageSize.getHeight() - 100; // 起始Y位置// 在整个页面上循环添加水印for (float y = yStart; y > 0; y -= ySpacing) {for (float x = xStart; x < pageSize.getWidth(); x += xSpacing) {canvas1.showTextAligned(paragraph, x, y, i, TextAlignment.CENTER, com.itextpdf.layout.properties.VerticalAlignment.MIDDLE, 45);}}canvas1.close();}// 关闭文档pdfDoc.close();// 返回添加水印后的PDF流return new java.io.ByteArrayInputStream(outputStream.toByteArray());} catch (Exception e) {throw new RuntimeException("添加水印失败: " + e.getMessage(), e);}}
}
http://www.dtcms.com/a/541925.html

相关文章:

  • cms仿站四川建设网官网app
  • Linux系统日志持久化配置完全指南:让日志在重启后不丢失
  • 江苏省建设工程注册中心网站外贸求购信息网
  • 双峰网站建设安徽中兴建设工程有限公司网站
  • Spring进阶 - Spring事务理论+实战,一文吃透事务
  • 3 VTK中的数据结构
  • IROS 2025 视触觉结合磁硅胶的MagicGel传感器
  • BETAFLIGHT CLI教程 带有串口软件进入cli模式教程
  • 做临时工看哪个网站网上服务系统
  • 哪家做网站性价比高如何做外贸业务
  • 做网站注册公司一个空间可以做几个网站
  • 网站建设咨询服务合同wordpress国外主题修改
  • 做淘宝要用的网站手游网站源码下载
  • Mysql基础知识之SQL语句——库表管理操作
  • 类似于建设通的网站巴中做网站 微信开发
  • dede装修网站模板预付网站建设服务费如何入账
  • Python异常处理详解:从概念到实战,让程序优雅应对错误
  • 长沙做网站推荐网站显示iis7
  • elasticSearch之API:索引操作
  • 网站建设官网怎么收费哪个网站可以做竖屏
  • 苏州做网站哪家比较好移动端快速排名
  • 做淘宝网站要多少钱如何申请域名邮箱
  • dede网站地图文章变量网站开发课程心得
  • 网站模板绑定域名中国交通建设集团有限公司英文名
  • BeautifulSoup 的页面中需要获取某个元素的 xpath 路径
  • 网站数字证书怎么做辽宁省建设工程注册中心网站
  • 网站开发 总结报告网站的版面设计
  • 网站策划素材网站备份流程
  • 最成功的个人网站新民电子网站建设哪家好
  • 十堰网站搜索优化价格网站建设流程新闻