2012-05-10 4 views
4

Я хотел бы заполнить форму PDF с помощью библиотеки javascript PDFBox. Форма PDF создается с помощью Adobe Live Designer, поэтому он использует формат XFA.Объединение XFA с PDFBox

Я пытаюсь найти ресурсы по заполнению форматов XFA PDF с помощью PDFBox, но до сих пор мне не повезло. Я видел, что в API доступен метод PDAcroForm.setXFA, но я не вижу, как его использовать.

Знаете ли вы, если можно заполнить PDF-форму PDFBox? Если да, есть ли где-нибудь образец кода или учебник для достижения этого? Если нет, то каковы наилучшие альтернативы для достижения этого?

ответ

2

Я не знаком с pdfbox, но вы можете сделать это с помощью iText (http://itextpdf.com/) после получения доступа к DOM XFA (XML).

+0

Я, наконец, выбрал itext. – OutOfBound

-1

AcroForm предназначен для PDF со статическими полями. Если PDF имеет формы xfa, вы можете использовать itext (Java) или itextsharp (.net) для заполнения ваших данных. Только проблема с формами XFA заключается в том, что они не могут быть Flatten с itext только способом Flatten, который я нашел, используя bullzip или аналогичный PDF-создатель, чтобы открыть этот xfa pdf, созданный с помощью itext, и передать его через 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, созданные и печати через BullZip

Const строка 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 ..

+5

Ну, мы ** всегда ** нуждаемся в коде. Поэтому, если вы можете предоставить банку, предоставьте ее. – j0k

+0

Это вопрос, отмеченный как Java. Bullzip недоступен для Java! –

5

Вопрос конкретно идентифицирует библиотеку PDFBox в субъекте; вам не нужен iText, манипуляция XFA может быть выполнена с использованием объекта PDXFA, доступного в PDFBox 1.8.

Огромное спасибо Маруан Сахьюн за отличную работу над PDFBox + XFA.

Этот код работает только при удалении всей безопасности в PDDocument.
Он также предполагает, что объект COS в PDXFA является 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); 
+0

В приведенном выше коде, что такое «documentBuilder»? –

+0

Я использовал приведенный выше код и немного обеспокоен тем, что полученный файл довольно большой. Файл PDF начинается с 647kb pdf. Новый pdf 14000kb. Кто-нибудь знает, как уменьшить размер создаваемого файла. Можно ли установить сжатие при записи в файл pdf? – chamalabey

+0

Код JammyDodger показывает только, как получить доступ к XML и как его вернуть. Не показывайте, как найти поля, как установить значения ... DocumentBuilder - это javax.xml.parsers.DocumentBuilder получить с помощью javax.xml.parsers.DocumentBuilderFactory, насколько я могу судить. неопределенная переменная xmlDoc - документ (моя догадка) –

3

Это лучшее, что я смог управлять в то время, когда я был назначен на проблему. Я получаю 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, иначе он не работает во всех зрителях.

Смежные вопросы