将XFA与PDFBox结合使用

我想用PDFBox java库填写PDF表单。 PDF表单是使用Adobe Live Designer创建的,因此它使用XFA格式。

我试图找到有关使用PDFBox填充XFA PDF表单的资源,但到目前为止我还没有运气。 我看到API中有一个PDAcroForm.setXFA方法,但我看不到如何使用它。

您知道是否可以用PDFBox填写PDF表格? 如果是,是否有任何代码示例或教程来实现这一目标? 如果不是,实现这一目标的最佳方案是什么?

该问题专门识别主题中的PDFBox库; 您不需要iText,可以使用PDFBox 1.8中提供的PDXFA对象完成XFA操作。

非常感谢Maruan Sahyoun在PDFBox + XFA上所做的出色工作。

此代码仅在删除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); 

这是我在分配问题时能够管理的最好的。 我将pdf保存(在生命周期中)优化(我不是那个做pdf的人)。 这是PDF开放部分,XML复制然后保存:

  PDDocument document = PDDocument.load(fileInputStream); fileInputStream.close(); document.setAllSecurityToBeRemoved(true); Map values = new HashMap(); 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 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 values) throws IOException { @SuppressWarnings("unchecked") List fields = pdfDocument.getDocumentCatalog().getAcroForm().getFields(); for (PDField pdField : fields) { setFields(pdField, values); } } private void setFields(PDField field, Map values) throws IOException { List 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生命周期产品,一些得到一个关于“扩展function”的警告信息不再启用但仍然有效。 优化版本是我发现的唯一一个在填写后打开时不提示消息的版本。

我填写XFA和Acroform,否则它不适用于所有查看器。

我不熟悉pdfbox,但是一旦您访问了XFA(XML)DOM,就可以使用iText( http://itextpdf.com/ )完成此操作。

AcroForm适用于带静态字段的PDF。 如果PDF有xfa表单,您可以使用itext(Java)或itextsharp(.net)来填充数据。 只有XFA表单的问题是他们不能使用itext展平Flatten我发现使用bullzip或类似的pdf创建者打开用itext创建的xfa pdf并通过bullzip传递它将吐出flatten pdf版本。 希望这会给你一些想法。

下面的代码只是一个粗略的想法如何填充xfa。

 XfaForm xfa = pdfFormFields.Xfa; dynamic bytes = Encoding.UTF8.GetBytes("  " + "\r\n" + barcode + " " + Extra + " "); MemoryStream ms = new MemoryStream(bytes); pdfStamper.AcroFields.Xfa.FillXfaForm(ms); 

您现在可以使用您创建的xfa pdf并通过bullzip进行打印

const string Printer_Name =“Bullzip PDF Printer”;

  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 ..