PDFBox:如何将PDAcroForm展平?

时间:2015-10-28 05:15:39

标签: java pdf pdf-generation pdfbox

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

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

但似乎没有任何效果。请为此建议一个解决方案。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

如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);
        }
    });
}