1. 概述

本文将详细介绍如何在Java中编辑现有PDF文件的内容。我们先从添加新内容开始,然后重点讲解如何删除或替换已存在的内容。

2. 添加iText7依赖

我们将使用iText7库向PDF文件添加内容,后续会使用pdfSweep插件来删除或替换内容。

⚠️ 注意:iText采用AGPL许可,可能会限制商业应用的分发:iText许可模型

首先在pom.xml中添加依赖:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.2.3</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>cleanup</artifactId>
    <version>3.0.1</version>
</dependency>

3. 文件处理

使用iText7处理PDF文件的核心步骤:

  • 首先通过PdfReader读取源文件内容(读取失败会抛出IOException
  • 然后通过PdfWriter写入目标文件(文件不存在或创建失败会抛出FileNotFoundException
  • 接着创建使用上述读写器的PdfDocument
  • 最后关闭PdfDocument会自动关闭底层的读写器

以下是完整的处理流程代码:

public static void main(String[] args) throws IOException {
    PdfReader reader = new PdfReader("src/main/resources/baeldung.pdf");
    PdfWriter writer = new PdfWriter("src/main/resources/baeldung-modified.pdf");
    PdfDocument pdfDocument = new PdfDocument(reader, writer);
    addContentToDocument(pdfDocument);
    pdfDocument.close();
}

后续我们将逐步完善addContentToDocument()方法。源文件是仅包含左上角文本"Hello Baeldung"的PDF,目标文件将由程序创建。

4. 向文件添加内容

4.1. 添加表单

我们先向文件添加一个简单表单,包含名为"name"的文本字段。

需要指定字段位置:坐标(35,400)(原点(0,0)在文档左下角),尺寸设为100×30

PdfFormField personal = PdfFormField.createEmptyField(pdfDocument);
personal.setFieldName("information");
PdfTextFormField name = PdfFormField.createText(pdfDocument, new Rectangle(35, 400, 100, 30), "name", "");
personal.addKid(name);
PdfAcroForm.getAcroForm(pdfDocument, true)
    .addField(personal, pdfDocument.getFirstPage());

✅ 显式指定表单添加到文档第一页

4.2. 添加新页面

使用addNewPage()方法添加新页面,可指定插入位置:

pdfDocument.addNewPage(1); // 在文档开头添加新页

4.3. 添加注解

注解类似方形对话框,我们将其添加到第二页的表单上方,位置(40,435)

PdfAnnotation ann = new PdfTextAnnotation(new Rectangle(40, 435, 0, 0)).setTitle(new PdfString("name"))
    .setContents("Your name");
pdfDocument.getPage(2)
    .addAnnotation(ann);

效果如下:

baeldung modified form and annotation

4.4. 添加图片

添加布局元素需要创建Document对象(直接操作PdfDocument已不可行):

Document document = new Document(pdfDocument);
// 添加布局元素
document.close(); // 关闭Document会自动关闭底层PdfDocument

通过ImageDataFactory加载图片(资源目录中的baeldung.png):

ImageData imageData = ImageDataFactory.create("src/main/resources/baeldung.png");

设置图片尺寸550×100,位置(10,50)

Image image = new Image(imageData).scaleAbsolute(550,100)
    .setFixedPosition(1, 10, 50);
document.add(image);

图片自动缩放效果:

baeldung modified p1 baeldung

4.5. 添加段落

iText提供文本添加工具,字体可单独设置或在Paragraph上全局设置。

在第一页顶部添加句子"This is a demo from Baeldung tutorials":

Text title = new Text("This is a demo").setFontSize(16);
Text author = new Text("Baeldung tutorials.");
Paragraph p = new Paragraph().setFontSize(8)
    .add(title)
    .add(" from ")
    .add(author);
document.add(p);

4.6. 添加表格

最后添加表格,创建2列表格并添加表头和数据:

Table table = new Table(UnitValue.createPercentArray(2));
table.addHeaderCell("#");
table.addHeaderCell("company");
table.addCell("name");
table.addCell("baeldung");
document.add(table);

文档第一页顶部效果:

baeldung modified p1 top

5. 从文件删除内容

5.1. 删除文本

需要定义清理策略,示例中删除所有"Baeldung"文本:

CompositeCleanupStrategy strategy = new CompositeCleanupStrategy();
strategy.add(new RegexBasedCleanupStrategy("Baeldung"));
PdfCleaner.autoSweepCleanUp(pdfDocument, strategy);

✅ 匹配文本会被黑色矩形覆盖(适合数据脱敏):

baeldung cleaned p1 top

5.2. 删除其他内容

⚠️ 非文本内容检测困难,但可通过区域擦除实现。

示例删除:

  • 第二页(35,400)100×35区域(表单和注解)
  • 第一页(10,50)90×70区域(logo的"B"字母)
List<PdfCleanUpLocation> cleanUpLocations = Arrays.asList(
    new PdfCleanUpLocation(1, new Rectangle(10, 50, 90,70)), 
    new PdfCleanUpLocation(2, new Rectangle(35, 400, 100, 35))
);
PdfCleanUpTool cleaner = new PdfCleanUpTool(pdfDocument, cleanUpLocations, new CleanUpProperties());
cleaner.cleanUp();

效果:

baeldung cleaned p1 baeldung

6. 替换文件内容

本节实现文本替换而非仅删除,使用新main方法处理。

源文件:baeldung-modified.pdf
目标文件:baeldung-fixed.pdf

核心思路:

  1. 将覆盖色改为白色(匹配文档背景)
  2. 搜索"Baeldung"文本
  3. 获取删除位置后写入替换文本"HIDDEN"
  4. 调整上边距改善对齐
CompositeCleanupStrategy strategy = new CompositeCleanupStrategy();
strategy.add(new RegexBasedCleanupStrategy("Baeldung").setRedactionColor(ColorConstants.WHITE));
PdfCleaner.autoSweepCleanUp(pdfDocument, strategy);

for (IPdfTextLocation location : strategy.getResultantLocations()) {
    PdfPage page = pdfDocument.getPage(location.getPageNumber() + 1);
    PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), page.getDocument());
    Canvas canvas = new Canvas(pdfCanvas, location.getRectangle());
    canvas.add(new Paragraph("HIDDEN").setFontSize(8)
        .setMarginTop(0f));
}

效果:

baeldung fixed p1 top

7. 总结

本文完整演示了PDF内容编辑的三大核心操作:

  • ✅ 添加新内容(表单/页面/注解/图片/段落/表格)
  • ❌ 删除现有内容(文本/区域内容)
  • 🔄 替换文本内容

所有示例代码可在GitHub仓库获取。实际开发中需特别注意iText的AGPL许可限制,商业项目建议评估替代方案。


原始标题:Editing Existing PDF Files in Java

« 上一篇: 在Java中验证URL