【问题标题】:PDFBox : How can a PDAcroForm be flattened? [duplicate]PDFBox:如何将 PDAcroForm 展平? [复制]
【发布时间】:2016-01-27 18:34:52
【问题描述】:

我正在使用 PDFBox 库来填充 PDF 表单,但我无法将它们展平。我已经尝试了以下解决方案:

 PDAcroForm acroForm = docCatalog.getAcroForm();
 PDField field = acroForm.getField( name );
 field.setReadonly(true); //Solution 1
 field.getDictionary().setInt("Ff",1);//Solution 2

但似乎没有任何效果。请提出相同的解决方案。

【问题讨论】:

  • 您谈论的是扁平化 PDF 表单,但提供的示例代码只是尝试将表单字段设置为只读,这与表单扁平化完全不同。那么你真正想要的是哪个?有人问,PDFBox 中的表单展平没有开箱即用的单方法调用支持,但它的低级 API 允许实现表单展平。但请注意,这是可能,而不是简单。我刚刚用谷歌搜索了一下,我看到的 PDFBox 表单展平方法大多被破坏或仅在特殊、简单的情况下有效。
  • 我想在数据填充后从 Acroform 中删除可编辑字段。我只能使用 PDFBox 找到上述方法来做同样的事情,但还没有运气。
  • 好的。您仅找到的代码是将字段设置为只读,而不是您想要的。正如您提到的表单是由数据填充的,我假设您希望在删除字段时该数据仍然可见。因此,在删除表单域之前,必须将表单内容复制到页面内容中。这不是微不足道的,我也没有工作代码。如果我有足够的时间,我会在以后研究它。
  • @Maruan 的回答表明 pdfbox 2.0 将包含一个显式的表单展平方法。因此,我不会尝试手动编码。
  • 好的。谢谢你。如果您发现了什么,请分享。

标签: java pdf pdf-generation pdfbox


【解决方案1】:

PDFBOX 2.0.0 有一个 PDAcroForm.flatten() 方法

【讨论】:

  • 啊,这是个有趣的消息。
  • PDFBox 2.0.0正式发布了吗?还是即将推出的版本?
  • 据我所知 pdfbox 2.0 候选版本 1 现已上市。
  • 嗯,我刚刚看了PDAcroForm.flatten() 代码。它看起来还没有完成。全局标志isContentStreamWrapped应该是一个标志字段,每页一个标志,此外它不会创建丢失的外观流。
  • isContentStreamWrapped -> 同意应该是不同的创建缺少的外观流 -> 这是故意的。创建缺少的外观流(并支持 NeedAppareances 标志)标记为 2.1。我也宁愿在一个单独的方法中完成,并让 flatten() 期望外观流确实存在。
【解决方案2】:

正如 Maruan 所说,可以使用PDAcroForm.flatten() 方法。

虽然字段可能需要一些预处理,最重要的是必须遍历嵌套字段结构并检查 DV 和 V 的值。

在我们的例子中起作用的是:

private static void flattenPDF(String src, String dst) throws IOException {
    PDDocument doc = PDDocument.load(new File(src));

    PDDocumentCatalog catalog = doc.getDocumentCatalog();
    PDAcroForm acroForm = catalog.getAcroForm();
    PDResources resources = new PDResources();
    acroForm.setDefaultResources(resources);

    List<PDField> fields = new ArrayList<>(acroForm.getFields());
    processFields(fields, resources);
    acroForm.flatten();

    doc.save(dst);
    doc.close();
}

private static void processFields(List<PDField> fields, PDResources resources) {
    fields.stream().forEach(f -> {
        f.setReadOnly(true);
        COSDictionary cosObject = f.getCOSObject();
        String value = cosObject.getString(COSName.DV) == null ?
                       cosObject.getString(COSName.V) : cosObject.getString(COSName.DV);
        System.out.println("Setting " + f.getFullyQualifiedName() + ": " + value);
        try {
            f.setValue(value);
        } catch (IOException e) {
            if (e.getMessage().matches("Could not find font: /.*")) {
                String fontName = e.getMessage().replaceAll("^[^/]*/", "");
                System.out.println("Adding fallback font for: " + fontName);
                resources.put(COSName.getPDFName(fontName), PDType1Font.HELVETICA);
                try {
                    f.setValue(value);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            } else {
                e.printStackTrace();
            }
        }
        if (f instanceof PDNonTerminalField) {
            processFields(((PDNonTerminalField) f).getChildren(), resources);
        }
    });
}

【讨论】:

    猜你喜欢
    • 2013-01-05
    • 2022-01-21
    • 1970-01-01
    • 2011-11-03
    • 2013-03-08
    • 2019-06-30
    • 2021-12-22
    • 1970-01-01
    • 2021-06-03
    相关资源
    最近更新 更多