我想用PDFBox Java庫填充PDF表單。 PDF表單使用Adobe Live Designer創建,因此它使用XFA格式。將XFA與PDFBox結合
我嘗試找到有關使用PDFBox填充XFA PDF表單的資源,但目前爲止我還沒有任何運氣。我看到API中有一個PDAcroForm.setXFA方法,但我不知道如何使用它。
你知道是否可以使用PDFBox填寫PDF表單嗎? 如果是的話,是否有任何代碼示例或教程來實現這一目標? 如果不是,那麼實現此目標的最佳選擇是什麼?
我想用PDFBox Java庫填充PDF表單。 PDF表單使用Adobe Live Designer創建,因此它使用XFA格式。將XFA與PDFBox結合
我嘗試找到有關使用PDFBox填充XFA PDF表單的資源,但目前爲止我還沒有任何運氣。我看到API中有一個PDAcroForm.setXFA方法,但我不知道如何使用它。
你知道是否可以使用PDFBox填寫PDF表單嗎? 如果是的話,是否有任何代碼示例或教程來實現這一目標? 如果不是,那麼實現此目標的最佳選擇是什麼?
我對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傳遞它,這將會吐出平坦的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);
您現在可以使用您創建的PDF XFA通過的BullZip
常量字符串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 ..
那麼,我們**總是**需要代碼。所以如果你能提供罐頭,就提供它。 – j0k
這是標記爲Java的問題。 Bullzip不適用於Java! –
問題具體地標識所述受試者中的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);
在上面的代碼中,「documentBuilder」是什麼? –
我使用了上面的代碼,並且由於生成的文件非常大而引起了一點關注。 PDF文件以647kb pdf開始。新的pdf 14000kb。任何人都知道如何減少生成的新文件的大小。回寫到pdf文件時可以設置某種類型的壓縮嗎? – chamalabey
JammyDodger代碼只顯示如何訪問XML以及如何恢復。不顯示如何查找字段,如何設置值... DocumentBuilder是一個javax.xml.parsers.DocumentBuilder,可以用javax.xml.parsers.DocumentBuilderFactory獲取,據我所見。未定義的變量xmlDoc是文檔(我的猜測) –
這是我在分配問題時能夠管理的最佳狀態。我將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生命週期生產的「種」,一些有關於「延長fonction」不再啓用,但仍然可以工作一個警告消息。優化版本是我發現的唯一一個在被填充後打開時不會提示消息的人。
我填充了XFA和Acroform,否則它不適用於所有查看器。
我終於選擇了itext。 – OutOfBound