8

PDFフォームにPDFBoxJavaライブラリを入力したいと思います。PDFフォームはAdobeLiveDesignerで作成されるため、XFA形式を使用します。

XFA PDFフォームにPDFBoxを入力するためのリソースを見つけようとしていますが、今のところ運がありません。APIでPDAcroForm.setXFAメソッドを使用できることを確認しましたが、使用方法がわかりません。

PDFフォームにPDFBoxを入力できるかどうか知っていますか?はいの場合、これを実現するためのコードサンプルまたはチュートリアルはどこかにありますか?いいえの場合、これを達成するための最良の選択肢は何ですか?

4

5 に答える 5

8

これは、この問題に割り当てられた時間内に管理できた最高のものです。最適化されたものとして(ライフサイクルで)保存されたpdfを取得します(私はpdfを実行していません)。これは、PDF の開始部分、XML の複製、および保存です。

    PDDocument document = PDDocument.load(fileInputStream);
    fileInputStream.close();
    document.setAllSecurityToBeRemoved(true);

    Map<String, String> values = new HashMap<String, String>();
    values.put("variable_name", "value");


    setFields(document, values); // see code below

    PDAcroForm form = document.getDocumentCatalog().getAcroForm();
    Document documentXML = form.getXFA().getDocument();

    NodeList dataElements = documentXML.getElementsByTagName("xfa:data");
    if (dataElements != null) {
        for (int i = 0; i < dataElements.getLength(); i++) {
            setXFAFields(dataElements.item(i), values);
        }
    }

    COSStream cosout = new COSStream(new RandomAccessBuffer());

    TransformerFactory.newInstance().newTransformer()
            .transform(new DOMSource(documentXML), new StreamResult(cosout.createUnfilteredStream()));

    form.setXFA(new PDXFA(cosout));

    FileOutputStream fios = new FileOutputStream(new File(docOut + ".pdf"));
    document.save(fios);
    document.close();
    try {
        fios.flush();
    } finally {
        fios.close();
    }

次に、フィールドの値を設定するメソッド。XFA と AcroForm の両方を設定します。

public void setXFAFields(Node pNode, Map<String, String> values) throws IOException {
    if (values.containsKey(pNode.getNodeName())) {
        pNode.setTextContent(values.get(pNode.getNodeName()));
    } else {
        NodeList childNodes = pNode.getChildNodes();
        if (childNodes != null) {
            for (int i = 0; i < childNodes.getLength(); i++) {
                setXFAFields(childNodes.item(i), values);
            }
        }
    }
}

public void setFields(PDDocument pdfDocument, Map<String, String> values) throws IOException {

    @SuppressWarnings("unchecked")
    List<PDField> fields = pdfDocument.getDocumentCatalog().getAcroForm().getFields();
    for (PDField pdField : fields) {
        setFields(pdField, values);
    }
}

private void setFields(PDField field, Map<String, String> values) throws IOException {
    List<COSObjectable> kids = field.getKids();
    if (kids != null) {
        for (COSObjectable pdfObj : kids) {
            if (pdfObj instanceof PDField) {
                setFields((PDField) pdfObj, values);
            }
        }
    } else {
        // remove the [0] from the name to match values in our map
        String partialName = field.getPartialName().replaceAll("\\[\\d\\]", "");
        if (!(field instanceof PDSignatureField) && values.containsKey(partialName)) {
            field.setValue(values.get(partialName));
        }
    }
}

これは機能しますが、すべての「種類」の PDF ライフサイクルで生成されるわけではありません。「拡張機能」が有効になっていないという警告メッセージが表示されるものもありますが、それでも機能します。最適化バージョンは、入力後に開いたときにメッセージを表示しない唯一のバージョンです。

XFA と Acroform を入力しないと、すべてのビューアーで機能しません。

于 2014-11-28T19:32:09.270 に答える
6

質問は、件名の PDFBox ライブラリを明確に識別します。iText は必要ありません。XFA 操作は、PDFBox 1.8 で利用可能な PDXFA オブジェクトを使用して実行できます。

PDFBox + XFA に関する素晴らしい仕事をしてくれた Maruan Sahyun に感謝します。

このコードは、PDDocument のすべてのセキュリティを削除した場合にのみ機能します。
また、PDXFA の COS オブジェクトが COSStream であることも前提としています。以下の単純な例では、xml ストリームを読み取り、それを PDF に書き戻します。

 PDDocument doc = PDDocument.load("filename");
 doc.setAllSecurityToBeRemoved(true);

 PDDocumentCatalog docCatalog = doc.getDocumentCatalog();
 PDAcroForm form = docCatalog.getAcroForm();

 PDXFA xfa = form.getXFA();
 COSBase cos = xfa.getCOSObject();
 COSStream coss = (COSStream) cos;
 InputStream cosin = coss.getUnfilteredStream();
 Document document = documentBuilder.parse(cosin);

 COSStream cosout = new COSStream(new RandomAccessBuffer());
 OutputStream out = cosout.createUnfilteredStream();

 TransformerFactory tFactory = TransformerFactory.newInstance();
 Transformer transformer = tFactory.newTransformer();
 DOMSource source = new DOMSource(xmlDoc);
 StreamResult result = new StreamResult(out);
 transformer.transform(source, result);

 PDXFA xfaout = new PDXFA(cosout);
 form.setXFA(xfaout);
于 2014-01-16T17:47:13.490 に答える
1

私は pdfbox に精通していませんが、XFA (XML) DOM にアクセスできれば、iText ( http://itextpdf.com/ ) でこれを行うことができます。

于 2012-05-16T19:20:24.633 に答える
-2

AcroForm は、静的フィールドを持つ PDF 用です。PDF に xfa フォームがある場合は、itext (Java) または itextsharp (.net) を使用してデータを入力できます。XFAフォームの唯一の問題は、itextでフラット化できないことです。私が見つけたフラット化する唯一の方法は、ブルジップまたは同様のpdfクリエーターを使用して、itextで作成されたxfa pdfを開き、フラット化されたpdfバージョンを吐き出すブルジップを介して渡すことです。これがあなたにいくつかのアイデアを与えることを願っています。

以下のコードは、xfa がどのように満たされるかを大まかに示したものです。

XfaForm xfa = pdfFormFields.Xfa;
dynamic bytes = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?> <form1> <staticform>" + "\r\n<barcode>" + barcode + "</barcode></staticform> <flowForm><Extra>" + Extra + "</Extra></flowForm> </form1>");
MemoryStream ms = new MemoryStream(bytes);
pdfStamper.AcroFields.Xfa.FillXfaForm(ms);

作成した xfa pdf を使用して、bulzip から印刷できます。

const string Printer_Name = "Bullzip PDF プリンター";

                    PdfSettings pdfSettings = new PdfSettings();
                    pdfSettings.PrinterName = Printer_Name;
                    pdfSettings.SetValue("Output", flatten_pdf);
                    pdfSettings.SetValue("ShowPDF", "no");
                    pdfSettings.SetValue("ShowSettings", "never");
                    pdfSettings.SetValue("ShowSaveAS", "never");
                    pdfSettings.SetValue("ShowProgress", "no");
                    pdfSettings.SetValue("ShowProgressFinished", "no");
                    pdfSettings.SetValue("ConfirmOverwrite", "no");
                    pdfSettings.WriteSettings(PdfSettingsFileType.RunOnce);
                    PdfUtil.PrintFile(xfa_pdffile, Printer_Name);

出力ファイルは平坦化されたpdfになります..

于 2012-12-06T16:55:35.230 に答える