【问题标题】:PDFBox inconsistent PDTextField behaviour after setValuesetValue 后 PDFBox 的 PDTextField 行为不一致
【发布时间】:2020-04-01 06:22:35
【问题描述】:

PDFBox setValue() 不是为每个 PDTextField 设置数据。它节省了几个领域。它不适用于在 getFullyQualifiedName() 中具有相似外观的字段。

注意:field.getFullyQualifiedName() { customdutiesa, customdutiesb, customdutiesc } 它适用于 customdutiesa,但不适用于 customdutiesb 和 customdutiesc 等...

@Test
public void testb3Generator() throws IOException {
    File f = new File(inputFile);

    outputFile = String.format("%s_b3-3.pdf", "123");

    try (PDDocument document = PDDocument.load(f)) {

        PDDocumentCatalog catalog = document.getDocumentCatalog();
        PDAcroForm acroForm = catalog.getAcroForm();
        int i = 0;
        for (PDField field : acroForm.getFields()) {
            i=i+1;
            if (field instanceof PDTextField) {
                PDTextField textField = (PDTextField) field;
                textField.setValue(Integer.toString(i));
            }
        }

        document.getDocumentCatalog().getAcroForm().flatten();

        document.save(new File(outputFile));
        document.close();
    }
    catch (Exception e) {

        e.printStackTrace();
    }
}

输入pdf链接:https://s3-us-west-2.amazonaws.com/kx-filing-docs/b3-3.pdf 输出pdf链接:https://kx-filing-docs.s3-us-west-2.amazonaws.com/123_b3-3.pdf

【问题讨论】:

    标签: java pdf-generation pdfbox acrofields


    【解决方案1】:

    问题在于,在某些情况下,PDFBox 不会为其设置值的字段构造外观,因此,在展平期间完全忘记了字段内容:

    // in case all tests fail the field will be formatted by acrobat
    // when it is opened. See FreedomExpressions.pdf for an example of this.  
    if (actions == null || actions.getF() == null ||
        widget.getCOSObject().getDictionaryObject(COSName.AP) != null)
    {
        ... generate appearance ...
    }
    

    (org.apache.pdfbox.pdmodel.interactive.form.AppearanceGeneratorHelper.setAppearanceValue(String))

    即如果存在与字段关联的值格式设置的 JavaScript 操作,并且尚不存在外观流,则 PDFBox 假定它不需要创建外观(并且可能无论如何都会做错,因为它不使用该格式操作)。

    万一以后用例将表单展平,那么 PDFBox 的假设显然是错误的。

    要强制 PDFBox 也为这些字段生成外观,只需在设置字段值之前删除操作:

    if (field instanceof PDTextField) {
        PDTextField textField = (PDTextField) field;
        textField.setActions(null);
        textField.setValue(Integer.toString(i));
    }
    

    (来自FillAndFlatten 测试testLikeAbubakarRemoveAction

    【讨论】:

    • @Abubakar 太棒了!尽管如此,您应该考虑 Tilman 从同时删除的评论中对您的问题的建议:acroForm.getFields() 不会返回所有字段的直接列表,仅返回顶级字段。通常,就像在您的示例文档中一样,只有顶级字段,但有时会有实际的字段层次结构。在这种情况下,您应该使用acroForm.getFieldTree()acroForm.getFieldIterator() 来访问所有字段。
    • 在当前情况下,我正在获取所有正在更新的字段。真的,这更有帮助。
    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 2018-06-02
    • 1970-01-01
    • 2017-02-03
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    相关资源
    最近更新 更多