【问题标题】:How to identify if a PDF file contains form fields如何识别 PDF 文件是否包含表单域
【发布时间】:2019-11-27 21:41:57
【问题描述】:

我们允许用户上传 PDF 文档供我们存储。我们警告用户在上传 PDF 之前必须将其拼合,但许多人仍然会上传包含表单域的 PDF 文档。我们希望通过在上传到我们的存储之前验证 PDF 文件来防止这种情况发生。

我们正在使用 iText-5.1 将文件作为字节 [] 读取并使用 PdfReader 打开它。然后我们使用 AcroFields() 提取字段并测试是否存在。目前 getFields().size() 总是返回 0 [见下面的代码],即使是我知道包含表单字段的测试 PDF。

PdfReader reader = new PdfReader(bytes);
AcroFields fields = reader.getAcroFields()
boolean hasFormFields = 
   (fields != null && fields.getFields() != null && fields.getFields().size() > 0);
if (hasFormFields) {
   // Report Error to User - throw exception, etc.
}

当 PDF 包含表单域元素时,我希望 getFields().size() 大于 0。还有其他方法可以使用 Java 和 iText 识别表单字段吗?

【问题讨论】:

  • 您显示的代码应该适用于所有 acroform 表单元素。您的示例文件是纯 xfa 格式吗?
  • 另一种可能性是你做扁平化,因为里面有表单域。但这可能取决于您的用户。 (我们的一些用户无法拼合他们的文档...)
  • @mkl 如何以编程方式识别 PDF 文件是否为“纯 xfa 格式”?那是 META-Data 中我能读懂的东西吗?
  • 要检查 XFA,请使用 fields.getXfa().isXfaPresent()。要检查 AcroForm,请使用您的代码。还有一种您可能希望避免的情况:当没有 AcroForm 字典或只有一个没有 Fields 数组或只有一个空 Fields 数组。要检查它们,您必须遍历文档页面并检查其所有注释的 Subtype 值。
  • 我终于明白了——这些 PDF 文件真的是 XFA,这就是我找不到 AcroForms 的原因。我添加了代码以排除 XFA 表单,这解决了我的问题。感谢大家对此的帮助。

标签: java pdf itext


【解决方案1】:

您使用了正确的方法来识别(有效)PDF 文件是否包含表单域。您描述的问题是如何处理不符合标准的 PDF 文件,这些文件也包含表单字段但确实存在一些问题,例如缺少 AcroField 字典、缺少 Fields 数组或其他。你有三种可能:

  1. 忽略这些情况,因为它们是边缘情况
  2. 确定问题(例如使用 Acrobat Preflight)并编写检查方法 对于那些情况。您可以在下面找到一个示例,我在其中编写了一个方法 识别缺少Fields 数组的文档。
  3. 只需将上传的所有文档展平即可。

以下代码检查您的方法返回 true 但仍包含表单字段的文档。这些字段也将显示在 *dobe 阅读器中。

   public boolean containsFormFields2() {

        AcroFields acroFields = reader.getAcroFields();

        if (acroFields.getFields() == null || acroFields.getFields().size() == 0) {
            // recheck "manually"
            for (int i = 1; i <= super.reader.getNumberOfPages(); i++) {
                PdfDictionary page = super.reader.getPageN(i);
                PdfArray annots = page.getAsArray(PdfName.ANNOTS);

                if (annots != null) {
                    // check for form fields in general
                    for (int j = 0; j < annots.size(); j++) {
                        PdfDictionary po2 = (PdfDictionary) annots.getDirectObject(j);

                        // FT key only exists for form fields
                        PdfName type = (PdfName) po2.get(PdfName.FT);
                        if (type != null) {
                           return true;
                        }
                    }
                }
            }
         return false;
        }
        else{
         return true;
        }
   }

【讨论】:

  • 我已将此代码添加到我的方法中,并且得到相同的结果... size = 0。我真的希望我可以发布 PDF,但数据是机密的。我会看看我是否可以获得我可以发布的示例 PDF。我非常感谢您的帮助。
  • 只有一个PDF吗?然后我会认为它是错误的。显然没有 Fields 数组。我稍微改变了上面的代码。能不能再执行一遍,告诉结果?
  • 去年提交的 PDF 文件大约有 4 打存在此表单字段问题。这是一个问题的原因是由于 Google Chrome 中的内部 PDF 查看器。它无法显示该文件。此外,由于数据具有敏感性质,我们不希望存储可编辑的数据。我真正想要的是只接受扁平化的 PDF 文件,但我不知道这样做的好方法(寻找表单字段实际上是一种尝试识别非扁平化 PDF 文件的技巧)。
  • 这可能是一个“黑客”,但它能够很好地识别是否存在不符合标准的 PDF。所以我很好奇:当您尝试这 4 个文档时,输出是什么?
  • “我真正想要的是只接受扁平化的 PDF 文件,但我不知道有什么好的方法” - 自己扁平化它们怎么样?跨度>
猜你喜欢
  • 2012-09-28
  • 2014-12-12
  • 1970-01-01
  • 2020-04-21
  • 2017-05-18
  • 2011-05-26
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
相关资源
最近更新 更多