基于 Java 的 PDF 文本水印实现方案(iText7 示例)

本文介绍如何使用 Java 在 PDF 文档上添加通用的文字水印,示例基于 iText7,强调实现思路和关键 API,便于在任意项目中复用或扩展。


1. 方案概览

  • 目标:在现有 PDF 文件的每一页上添加居中、斜向、半透明的文字水印,例如「xx公司」。

  • 适用场景

    • 预览/下载前对 PDF 加防泄露水印;
    • 批量归档 PDF 时统一添加版权信息;
    • 按用户或租户动态生成个性化水印(用户名、时间、IP 等)。
  • 核心技术栈

    • Java 8+;
    • iText7(com.itextpdf:itext7-core);
    • 如需中文,建议引入中文字体依赖(如 font-asian 或自备 TTF/OTF 字体)。

2. 基本依赖配置示例(Maven)

复制代码

<dependencies> <!-- iText7 主依赖(PDF 内核) --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.2.5</version> <type>pom</type> </dependency> ​ <!-- 可选:中文字体支持(也可以使用自带 TTF 字体文件) --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>font-asian</artifactId> <version>7.2.5</version> </dependency> </dependencies>

实际版本号可按项目统一依赖管理调整。


3. 实现思路

  1. 使用 PdfReader 读取原始 PDF 输入流(或文件)。

  2. 使用 PdfWriter 将处理结果写入输出流(内存或新文件)。

  3. 构造 PdfDocument 与高级布局对象 Document

  4. 选择合适的字体(特别是包含中文的字体)。

  5. 遍历 PDF 的每一页,计算页面中心坐标,在对应页上绘制水印 Paragraph

    • 文本内容:例如「xx公司」或某个动态字符串;
    • 字体、字号、颜色、透明度;
    • 旋转角度(如 45°)与对齐方式(居中)。
  6. 关闭文档,输出带水印的 PDF。


4. 示例代码:为每页添加对角线文字水印

复制代码

import com.itextpdf.io.font.PdfEncodings; import com.itextpdf.kernel.colors.DeviceRgb; import com.itextpdf.kernel.font.PdfFont; import com.itextpdf.kernel.font.PdfFontFactory; import com.itextpdf.kernel.geom.Rectangle; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.properties.TextAlignment; import com.itextpdf.layout.properties.VerticalAlignment; ​ import java.io.ByteArrayOutputStream; import java.io.InputStream; ​ public class PdfWatermarkUtil { ​ /** * 为 PDF 每一页添加斜向文字水印 * * @param pdfInput 原始 PDF 输入流 * @param watermark 水印文本(如 "xx公司") * @return 带水印 PDF 的字节数组 */ public static byte[] addTextWatermark(InputStream pdfInput, String watermark) throws Exception { try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { PdfReader reader = new PdfReader(pdfInput); PdfWriter writer = new PdfWriter(out); PdfDocument pdfDoc = new PdfDocument(reader, writer); Document document = new Document(pdfDoc); ​ PdfFont font = createFont(); ​ int totalPages = pdfDoc.getNumberOfPages(); for (int i = 1; i <= totalPages; i++) { Rectangle pageSize = pdfDoc.getPage(i).getPageSize(); float x = (pageSize.getLeft() + pageSize.getRight()) / 2; float y = (pageSize.getTop() + pageSize.getBottom()) / 2; ​ Paragraph p = new Paragraph(watermark) .setFont(font) .setFontSize(60) .setFontColor(new DeviceRgb(192, 192, 192)) .setOpacity(0.3f); ​ document.showTextAligned( p, x, y, i, TextAlignment.CENTER, VerticalAlignment.MIDDLE, (float) Math.toRadians(45) ); } ​ document.close(); pdfDoc.close(); return out.toByteArray(); } } ​ /** * 创建字体(示例:使用系统或自带的中文字体) */ private static PdfFont createFont() throws Exception { // 示例:使用内置字体或自带 TTF 文件 // 1)若有自定义字体: // return PdfFontFactory.createFont("/path/to/simsun.ttf", PdfEncodings.IDENTITY_H, true); // 2)简化示例:使用内置字体(不保证完整中文支持) return PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true); } }


5. 关键点与扩展建议

  • 字体选择 :对中文 PDF,尽量使用包含中文的 TTF/OTF 字体文件,并通过 PdfEncodings.IDENTITY_H 创建嵌入字体,避免乱码。

  • 透明度与字号 :可根据实际打印/预览效果调整水印的字号和 setOpacity,在可见与不干扰阅读之间取得平衡。

  • 动态水印:业务代码中通常不会写死「xx公司」,而是将水印文案作为参数传入,例如「xx公司(机密)」或「用户名+时间戳」。

  • 性能考虑:对于非常大的 PDF(页数很多),可以:

    • 控制只对部分页面加水印;
    • 或在异步任务/批处理服务中执行水印操作。
  • 安全性:水印不能防止专业的 PDF 编辑/篡改,但对一般用户的泄露行为有一定威慑与追责作用,可结合权限控制一同使用。


6. 总结

使用 iText7 给 PDF 添加文字水印的核心就是:读取现有 PDF → 遍历页面 → 在每页叠加一层半透明文本 。上面的封装方法只依赖 InputStream 与文案字符串,便于集成到上传、下载或文件转换链路中,实现统一的 PDF 水印策略。

相关推荐
不懒不懒1 小时前
【决策树算法实战指南:从原理到Python实现】
python·决策树·id3·c4.5·catr
马猴烧酒.2 小时前
【面试八股|Java集合】Java集合常考面试题详解
java·开发语言·python·面试·八股
天空属于哈夫克32 小时前
Java 版:利用外部群 API 实现自动“技术开课”倒计时提醒
数据库·python·mysql
测试工程师成长之路2 小时前
Serenity BDD 框架:Java + Selenium 全面指南(2026 最新)
java·开发语言·selenium
lang201509282 小时前
Java JSON绑定API:JSR 367详解
java·java-ee
喵手2 小时前
Python爬虫实战:全站 Sitemap 自动发现 - 解析 sitemap.xml → 自动生成抓取队列的工业级实现!
爬虫·python·爬虫实战·零基础python爬虫教学·sitemap·解析sitemap.xml·自动生成抓取队列实现
luoluoal2 小时前
基于深度学习的web端多格式纠错系统(源码+文档)
python·mysql·django·毕业设计·源码
eWidget2 小时前
随机森林原理:集成学习思想 —— Java 实现多棵决策树投票机制
java·数据库·随机森林·集成学习·金仓数据库
深蓝海拓2 小时前
PySide6从0开始学习的笔记(二十七) 日志管理
笔记·python·学习·pyqt