XFA 在 PDFBox 1.8.12 中构建,而不是在 2.0.4 中

XFA building in PDFBox 1.8.12, not in 2.0.4

我尝试从文件中提取 XFA,在我将 PDFBox 从 1.8.12 更新到 2.0.4 之前它对我来说工作正常。

我有一个文件,我可以使用 1.8.12 提取 XFA,但不能使用 2.0.4。

当我使用 PDFBox 使用 2.0.4 提取它时,我得到了 XFA 的结构,但几乎所有的值都丢失了。另一方面,当我尝试使用 1.8.12 提取相同的表单时,结果很好。

我在 SO 上调查了类似的问题。据说在 2.0.4 中修复了,但我仍然面临问题。

有什么想法吗?

我已经包含了文件

Generated XFA-1.8.12

Generated XFA-2.0.4

File used

编辑#1

对于 2.0.4

    // returns PDXFA
    public static byte[] getParsableXFAForm(File file) {
        if (file == null)
            return null;
        PDDocument doc;
        PDDocumentCatalog catalog;
        PDAcroForm acroForm;

        PDXFAResource xfa;
        try {
//            String pass = null;
            doc = PDDocument.load(file);
            if (doc == null)
                return null;
//             flattenPDF(doc);
            doc.setAllSecurityToBeRemoved(true);
            // System.out.println("Security " + doc.isAllSecurityToBeRemoved());
            catalog = doc.getDocumentCatalog();
            if (catalog == null) {
                doc.close();
                return null;
            }
            acroForm = catalog.getAcroForm();
            if (acroForm == null) {
                doc.close();
                return null;
            }
            xfa = acroForm.getXFA();
            if (xfa == null) {
                doc.close();
                return null;
            }
            // TODO return byte[]
            byte[] xfaBytes = xfa.getBytes();
            doc.close();
            return xfaBytes;
        } catch (IOException e) {
            // handle IOException
            // happens when the file is corrupt.
            e.printStackTrace();
            System.out.println("XFAUtils-getParsableXFAForm-IOException");
            return null;
        }
    }

对于 1.8.12

public static byte[] getParsableXFAForm(File file) {
        if (file == null)
            return null;
        PDDocument doc;
        PDDocumentCatalog catalog;
        PDAcroForm acroForm;
        PDXFA xfa;
        try {
            doc = PDDocument.loadNonSeq(file, null);
            if (doc == null)
                return null;
            // flattenPDF(doc);
            doc.setAllSecurityToBeRemoved(true);
            // System.out.println("Security " + doc.isAllSecurityToBeRemoved());
            catalog = doc.getDocumentCatalog();
            if (catalog == null) {
                doc.close();
                return null;
            }
            acroForm = catalog.getAcroForm();

            if (acroForm == null) {
                doc.close();
                return null;
            }
            xfa = acroForm.getXFA();
            if (xfa == null) {
                doc.close();
                return null;
            }
            // TODO return byte[]
            byte[] xfaBytes = xfa.getBytes();
            doc.close();
            return xfaBytes;
        } catch (IOException e) {
            // handle IOException
            // happens when the file is corrupt.
//          e.printStackTrace();
            System.out.println("XFAUtils-getParsableXFAForm-IOException");
            return null;
        }
}

乍一看

你的PDF修改了6次,期间填了XFA表格越来越多。您的 1.8.12 代码提取最新版本的 XFA 表单,而您的 2.0.4 代码提取最旧版本的 XFA 表单。

我 运行 您的 2.0.4 代码使用 PDFBox 版本 2.0.4、2.0.5 和当前开发快照 2.1.0-SNAPSHOT。在版本 2.0.4 中,我确实可以重现加载了 XFA 表单的最旧版本,但是使用 2.0.5 或 2.1.0-SNAPSHOT 加载了当前版本。

这似乎是 PDFBox 2.0.0...2.0.4 中的一个缺点,已在 2.0.5 中修复。

仔细检查

作为 PDFBox 2.0.4 中的错误,从文件的错误修订中读取 XFA 表单似乎不太可信,我对此进行了更多调查。

特别是我仔细查看了 PDF 文件本身。事实上,文件在实际 PDF 文件头之前有 10 个垃圾字节!

这些额外的垃圾字节使得相对于文件开头的交叉引用和偏移量都是错误的。因此,PDFBox 无法以常规方式解析文件,而是必须进行某种修复。

查看 2.0.4 和 2.0.5 之间的差异,特别是代码发生了重大变化,以修复具有损坏的交叉引用和偏移量的 PDF。虽然 PDFBox 2.0.4 只能部分修复文件(仅找到初始 XFA 修订版),但 PDFBox 2.0.5 成功修复了更完整的文件,特别是找到了最新的 XFA 修订版。


修复了 OP 的 PDF(即删除了前导垃圾字节,参见 XFA-File-fixed.pdf),我可以使用 PDFBox 版本 2.0.0...2.0.4 成功提取当前的 XFA 表单修订版,也是。

因此,这不是我最初假设的 PDFBox 错误,而只是一个损坏的 PDF 文件,在 PDFBox 2.0.5 改进之前,PDFBox 文件修复功能无法正确修复它。