在日常开发中,PDF 文档的生成与编辑几乎是绕不开的活儿——生成报表、添加水印、替换图片、加密分发,每一项都离不开一套稳定趁手的工具。最近在项目中梳理了一套完整的 PDF 操作方案,涵盖了增、删、改、查以及安全保护等常见场景,这里把踩过的坑和落地的代码整理出来,希望能给有类似需求的同学一点参考。

## 一、环境配置
工欲善其事,必先利其器。这里用的是 **Spire.PDF for Ja va**,API 很全,覆盖了绝大多数 PDF 操作。如果你用 Ma ven,在 `pom.xml` 里加上仓库和依赖就行:
```xml
com.e-iceblue
e-iceblue
https://repo.e-iceblue.com/nexus/content/groups/public/
e-iceblue
spire.pdf
11.9.6
```
不用 Ma ven 的话,直接去官网下载 JAR 包扔进项目 classpath 也行。搞定依赖之后,就可以开始写代码了。
## 二、加载文档
所有操作的第一步,都是把 PDF 文件加载到内存,得到一个 `PdfDocument` 对象:
```ja va
PdfDocument doc = new PdfDocument();
doc.loadFromFile("C:\\work\\sample.pdf");
```
`loadFromFile` 支持绝对路径和相对路径,加载成功后,后续的增删改查都围绕这个文档对象来操作。
## 三、内容添加
### 3.1 添加页面
如果需要在文档末尾追加一个新页面,用 `getPages().add()` 就行:
```ja va
PdfPageBase newPage = doc.getPages().add(PdfPageSize.A4, new PdfMargins(54));
newPage.getCanvas().drawString("这是新添加的页面内容",
new PdfTrueTypeFont(new Font("微软雅黑", Font.PLAIN, 18)),
PdfBrushes.getBlue(), 0, 0);
```
这段代码创建了一个 A4 大小的页面,左右边距 54 点,然后在左上角画了一行蓝色文字。`drawString` 支持指定字体、颜色和坐标,灵活度很高。
### 3.2 添加文字
如果要在已有页面的某个矩形区域内插入文字,并且希望自动换行,可以这样写:
```ja va
PdfPageBase page = doc.getPages().get(0);
Rectangle2D.Float rect = new Rectangle2D.Float(54, 300, 400, 100);
PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("宋体", Font.PLAIN, 14));
PdfSolidBrush brush = new PdfSolidBrush(new PdfRGBColor(Color.BLACK));
page.getCanvas().drawString("这段文字将被绘制在指定的矩形区域内,超出部分会自动换行。", font, brush, rect);
```
通过 `Rectangle2D.Float` 定义区域的位置和大小,文字会自动换行,非常适合填充表格或者写注释。
### 3.3 插入图片
往 PDF 里插图片(比如 Logo、签名)也很简单:
```ja va
PdfImage image = PdfImage.fromFile("C:\\work\\logo.png");
page.getCanvas().drawImage(image, 100, 500);
```
`fromFile` 加载图片文件,`drawImage` 绘制到指定坐标(左上角)。如果需要缩放,可以传入宽度和高度参数的重载方法。
### 3.4 添加表格
表格是数据展示的常用方式,Spire.PDF 支持从二维数组直接生成表格:
```ja va
PdfTable table = new PdfTable();
String[][] data = {
{"姓名", "部门", "入职年份"},
{"张明", "研发", "2019"},
{"李丽", "市场", "2020"},
{"王强", "财务", "2018"}
};
table.setDataSource(data);
// 自定义表格样式
PdfTableStyle style = new PdfTableStyle();
style.getDefaultStyle().setFont(new PdfTrueTypeFont(new Font("Arial", Font.PLAIN, 12)));
table.setStyle(style);
// 在页面上绘制表格
table.draw(page, new Point2D.Float(50, 200));
```
`setDataSource` 接受数据源,`draw` 方法指定表格左上角的起始坐标。样式支持字体、边框、背景色等自定义,够用。
### 3.5 添加注释
弹出式注释能增加文档的交互性,比如批注或提醒:
```ja va
PdfPopupAnnotation popup = new PdfPopupAnnotation();
popup.setLocation(new Point2D.Double(200, 400));
popup.setText("请确认此数据是否准确。");
popup.setIcon(PdfPopupIcon.Comment);
popup.setColor(new PdfRGBColor(Color.YELLOW));
page.getAnnotations().add(popup);
```
`setLocation` 设定注释图标的位置,`setText` 填入提示内容,最后加到页面的注释集合里。
## 四、内容替换
### 4.1 替换文字
批量修改文档中的特定词汇时,文本替换功能很实用。比如把全文的“Water”替换成“H₂O”:
```ja va
PdfTextReplaceOptions options = new PdfTextReplaceOptions();
options.setReplaceType(EnumSet.of(ReplaceActionType.IgnoreCase)); // 忽略大小写
for (int i = 0; i < doc.getPages().getCount(); i++) {
PdfPageBase page = doc.getPages().get(i);
PdfTextReplacer replacer = new PdfTextReplacer(page);
replacer.setOptions(options);
replacer.replaceAllText("Water", "H₂O");
}
```
`PdfTextReplacer` 针对每一页执行替换,`ReplaceActionType.IgnoreCase` 表示不区分大小写。注意这个方法只对文本内容有效,图片或扫描件不行。
### 4.2 替换图片
如果文档里的某张图片需要更新(比如换 Logo),可以按以下步骤操作:
```ja va
PdfImageHelper helper = new PdfImageHelper();
PdfImageInfo[] imageInfos = helper.getImagesInfo(page); // 获取页面上所有图片信息
PdfImage newImage = PdfImage.fromFile("C:\\work\\new_logo.png");
helper.replaceImage(imageInfos[0], newImage); // 替换第一张图片
```
`getImagesInfo` 返回图片信息数组,`replaceImage` 根据索引或具体信息替换。如果需要替换指定位置的图片,可以遍历 `imageInfos` 对比坐标后再操作。
## 五、内容删除
### 5.1 删除页面
```ja va
doc.getPages().removeAt(0); // 删除第一页
```
`removeAt` 接收页码索引(从 0 开始),执行后该页即被移除。
### 5.2 删除图片
```ja va
helper.deleteImage(imageInfos[0]); // 删除第一张图片
```
通过 `PdfImageHelper` 获取图片信息后调用 `deleteImage`。
### 5.3 删除注释
```ja va
page.getAnnotationsWidget().removeAt(0); // 删除第一个注释
```
`getAnnotationsWidget` 返回注释集合,`removeAt` 按索引移除。
### 5.4 删除附件
如果文档包含附件(比如嵌入的 PDF 或 Excel 文件),可以这样清理:
```ja va
PdfAttachmentCollection attachments = doc.getAttachments();
if (attachments.size() > 0) {
attachments.removeAt(0);
}
```
先获取附件集合,判断非空后删除指定索引的附件。
## 六、安全保护
### 6.1 添加水印
为了保护版权或标识文档状态,常需要添加文本水印。下面这段代码在每一页的中心位置绘制半透明的“机密”字样:
```ja va
PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("黑体", Font.PLAIN, 50), true);
String watermark = "机密";
float opacity = 0.3f;
for (int i = 0; i < doc.getPages().getCount(); i++) {
PdfPageBase page = doc.getPages().get(i);
page.getCanvas().setTransparency(opacity);
Dimension2D textSize = font.measureString(watermark);
double x = (page.getActualSize().getWidth() - textSize.getWidth()) / 2;
double y = (page.getActualSize().getHeight() - textSize.getHeight()) / 2;
page.getCanvas().drawString(watermark, font, PdfBrushes.getGray(), x, y);
}
```
通过 `setTransparency` 控制透明度,`measureString` 计算文字宽度以实现水平垂直居中。
### 6.2 加密保护
敏感文档需要密码加密,防止未授权访问。下面使用 AES-256 算法加密,并限制编辑和复制权限:
```ja va
String userPassword = "user123";
String ownerPassword = "admin456";
PdfPasswordSecurityPolicy policy = new PdfPasswordSecurityPolicy(userPassword, ownerPassword);
policy.setEncryptionAlgorithm(PdfEncryptionAlgorithm.AES_256);
policy.setDocumentPrivilege(PdfDocumentPrivilege.getAllowAll());
policy.getDocumentPrivilege().setAllowModifyContents(false);
policy.getDocumentPrivilege().setAllowContentCopying(false);
doc.encrypt(policy);
```
`userPassword` 用于打开文档,`ownerPassword` 用于管理权限。通过 `setDocumentPrivilege` 可以精细控制是否允许打印、修改、复制等操作。
## 七、保存与释放
所有操作完成后,把修改后的文档保存到新路径,并关闭资源:
```ja va
doc.sa veToFile("C:\\work\\output.pdf");
doc.close();
```
建议用新文件名保存,避免覆盖原始文件。
## 结语
以上这套方案覆盖了项目中常用的 PDF 操作——添加、替换、删除、水印和加密,借助成熟的第三方库,代码简洁且易于扩展。如果手头有类似的 PDF 处理任务,不妨参考这些示例,应该能快速落地。实际使用时,根据具体需求调整参数就好。
本文转载于:https://www.jb51.net/program/367218tqh.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。