Java 设置 PDF 表单域只读或扁平化

PDF 表单填写完成后,有时需要保留表单域但禁止继续修改,有时则需要直接移除字段的交互属性,生成用于提交或归档的最终文件。

在 Java 中,可以将整个 PDF 表单或指定表单域设置为只读,也可以将全部或指定表单域扁平化。本文分别介绍这几种处理方法,并说明只读和扁平化在实际使用中的区别。

添加 PDF 处理库

下面的示例通过 Spire.PDF for Java 处理 PDF 表单。使用 Maven 时,可在 pom.xml 中添加其 Maven 仓库和依赖:

xml 复制代码
<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>12.8.6</version>
    </dependency>
</dependencies>

使用 Java 将 PDF 表单设置为只读

如果需要保留表单域及其中的数据,但不允许用户继续填写,可以通过 ​​PdfFormWidget.setReadOnly()​​ 将整个表单设置为只读。

java 复制代码
import com.spire.pdf.PdfDocument;
import com.spire.pdf.widget.PdfFormWidget;

public class SetFormReadOnly {
    public static void main(String[] args) {

        // 加载 PDF 表单
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("申请表.pdf");

        // 获取表单并设置为只读
        PdfFormWidget form = (PdfFormWidget) pdf.getForm();
        form.setReadOnly(true);

        // 保存结果
        pdf.saveToFile("申请表_只读.pdf");
        pdf.close();
    }
}

设置为只读以后,表单域仍然保留在 PDF 中,因此后续程序仍然可以获取字段名称、读取字段值或进行其他表单处理。

如果只需要限制某一个字段,可以先取得对应的 ​​PdfField​​,再调用 ​​setReadOnly()​​:

java 复制代码
import com.spire.pdf.PdfDocument;
import com.spire.pdf.fields.PdfField;
import com.spire.pdf.widget.PdfFormWidget;

public class SetFieldReadOnly {
    public static void main(String[] args) {

        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("申请表.pdf");

        PdfFormWidget form = (PdfFormWidget) pdf.getForm();

        // 根据字段名称获取表单域
        PdfField field = form.getFieldsWidget().get("RequestAmount");

        if (field != null) {
            field.setReadOnly(true);
        }

        pdf.saveToFile("申请表_部分只读.pdf");
        pdf.close();
    }
}

按字段处理时,代码中使用的是 PDF 内部的字段名称,而不是页面上显示的标题。如果模板由其他人员制作,可以先读取字段名称,再确认程序需要操作的目标字段。

例如:

ini 复制代码
PdfFormWidget form = (PdfFormWidget) pdf.getForm();

for (int i = 0; i < form.getFieldsWidget().getCount(); i++) {
    PdfField field = form.getFieldsWidget().get(i);
    System.out.println(field.getName());
}

对于经常更新的 PDF 模板,最好不要依赖字段索引,因为字段顺序变化后,原来的索引可能对应到其他字段。

使用 Java 扁平化 PDF 中的所有表单域

如果不需要继续保留表单结构,可以通过 ​​isFlatten(true)​​ 将整个表单扁平化。

typescript 复制代码
import com.spire.pdf.PdfDocument;

public class FlattenForm {
    public static void main(String[] args) {

        // 加载填写完成的 PDF 表单
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("审批表.pdf");

        // 扁平化所有表单域
        pdf.getForm().isFlatten(true);

        // 保存结果
        pdf.saveToFile("审批表_扁平化.pdf");
        pdf.close();
    }
}

扁平化后,字段当前显示的内容会保留在 PDF 页面中,但原来的文本框、复选框、下拉列表等交互式表单域将不再作为可填写字段使用。

因此,如果程序还需要读取或修改表单数据,应在扁平化之前完成。

使用 Java 扁平化指定的表单域

也可以通过 ​​PdfField.setFlatten()​​ 只处理指定字段,而保留其他表单域。

java 复制代码
import com.spire.pdf.PdfDocument;
import com.spire.pdf.fields.PdfField;
import com.spire.pdf.widget.PdfFormWidget;

public class FlattenField {
    public static void main(String[] args) {

        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("申请表.pdf");

        PdfFormWidget form = (PdfFormWidget) pdf.getForm();

        // 获取指定表单域
        PdfField field = form.getFieldsWidget().get("RequestAmount");

        if (field != null) {
            field.setFlatten(true);
        }

        pdf.saveToFile("申请表_部分扁平化.pdf");
        pdf.close();
    }
}

这种方式适合只需要固定部分字段内容,而其他字段仍需继续填写的情况。

在实际代码中,建议检查字段是否存在。否则模板字段名称发生变化后,后续操作容易直接出现空指针异常。

只读和扁平化有什么区别?

只读和扁平化都可以让用户无法正常修改字段,但两者对 PDF 表单结构的处理不同。

对比项 设置只读 扁平化
保留表单域
用户可继续填写
可继续按字段名称读取数据
可重新修改字段属性

如果 PDF 后面仍然需要参与数据读取、表单校验或其他自动化处理,保留字段并设置为只读通常更方便。

如果 PDF 已经不再作为表单使用,只需要保留最终显示结果,则可以进行扁平化。

另外,这两个功能都只针对表单域本身。将字段设置为只读或进行扁平化,并不等同于限制整个 PDF 文件的编辑、复制或打印。如果需要控制这些权限,应另外使用 PDF 权限设置;如果需要验证文件内容是否被修改,则应使用数字签名。

使用时需要注意的几点

处理固定模板时,建议优先通过字段名称定位表单域,而不是依赖字段索引。对于由外部提供或经常调整的模板,可以在开发阶段先输出所有字段名称,确认内部字段定义。

扁平化还应该放在字段读取、赋值和校验之后。一旦生成最终的扁平化文件,后续逻辑就不应该继续依赖原来的表单域结构。

如果程序部署在服务器上,还需要检查扁平化后的实际显示结果,尤其是使用中文字体、自定义字体或特殊符号的字段。开发环境和服务器字体环境不同,有时会导致最终页面的文字显示发生变化。

结语

对于需要长期维护的业务系统,最好保留原始的可编辑 PDF,同时另存只读版或扁平化后的最终文件。这样即使后续模板、数据或业务流程发生变化,也不必尝试从已经处理过的文件中恢复原来的表单结构。

相关推荐
luteres1 小时前
Spring学习笔记
java·后端·spring
南城以南溫暖如初1472 小时前
从零搭建24小时自助健身系统:技术选型与核心模块实战
java·spring boot·redis·mysql·vue·mybatis
重生之后端学习2 小时前
53. 最大子数组和[中等]✅
java·数据结构·算法·leetcode·职场和发展
XS0301062 小时前
【无标题】
java·tomcat·maven·intellij-idea
陈皮波比茶2 小时前
java日志框架
java
thefool1122662 小时前
随机链表的复制
java
jvmind_dev2 小时前
SWT 堆外内存泄漏排查实录:一次 PNG 保存泄漏一张图,一行 g_free 治好
java·后端
CodeStats2 小时前
《源纹天书》第三百四十六章至第三百五十章:边界的扩张、跨宇宙通信的尝试、其他宇宙的回应、新网络的形成、宇宙网络的创始者!
java·源纹天书
古法安卓3 小时前
Android-显示流程
android·java·android studio