1

I'm trying to set the values in a pdf form that has dynamic input fields but I keep getting an error with a stream writer.

I have researched the steps to fill the form (http://mail-archives.apache.org/mod_mbox/pdfbox-users/201510.mbox/browser) and read similar questions Combining XFA with PDFBox and PDFBox bloated PDF file size

Is there a different way to do it? Any tips that could lead me in the right direction?

This is my code

PDDocument doc = null;
FileOutputStream fos = null;
COSStream cosout = null;

try {
    doc = PDDocument.load(new File(pdfTemplatePath));
    doc.setAllSecurityToBeRemoved(true);

    PDDocumentCatalog cat = doc.getDocumentCatalog();
    PDAcroForm aform = cat.getAcroForm();

    if (aform.hasXFA()) {

        PDXFAResource xfa = aform.getXFA();
        org.w3c.dom.Document xmlDoc = xfa.getDocument();

        Node xfaData = xmlDoc.getElementsByTagName("xfa:data").item(0);
        HashMap<String, String> xmlFields = new HashMap<String, String>();

        setDataElements(xfaData, xmlFields); //I set node contents here
        //System.out.println(xmlFields);

        cosout = new COSStream(new ScratchFile(new File("C://tests//")));

        TransformerFactory.newInstance().newTransformer()
                .transform(new DOMSource(xmlDoc), new StreamResult(cosout.createOutputStream()));

        PDXFAResource resout = new PDXFAResource(cosout);

        aform.setXFA(resout);

    }

    fos = new FileOutputStream(tempFilePath);

    doc.save(fos);
    doc.close();

} catch (Exception e) {
    e.printStackTrace();
    success = false;
} catch (Error err) {
    err.printStackTrace();
    success = false;
} finally {
    if (doc != null)
        doc.close();
    if (fos != null)
        fos.close();
    if (cosout != null)
        cosout.close();
}

This is the error I get

*java.lang.IllegalStateException: Cannot read while there is an open stream writer
        at org.apache.pdfbox.cos.COSStream.createRawInputStream(COSStream.java:133)
        at org.apache.pdfbox.pdfwriter.COSWriter.visitFromStream(COSWriter.java:1203)
        at org.apache.pdfbox.cos.COSStream.accept(COSStream.java:388)
        at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObject(COSWriter.java:522)
        at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObjects(COSWriter.java:460)
        at org.apache.pdfbox.pdfwriter.COSWriter.doWriteBody(COSWriter.java:444)
        at org.apache.pdfbox.pdfwriter.COSWriter.visitFromDocument(COSWriter.java:1099)
        at org.apache.pdfbox.cos.COSDocument.accept(COSDocument.java:419)
        at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1370)
        at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1257)
        at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1278)*

I tried closing the stream right before saving the document (I didn't see anyone doing it the examples I read) but then I got another error

*java.io.IOException: COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
        at org.apache.pdfbox.cos.COSStream.checkClosed(COSStream.java:82)
        at org.apache.pdfbox.cos.COSStream.createRawInputStream(COSStream.java:130)
        at org.apache.pdfbox.pdfwriter.COSWriter.visitFromStream(COSWriter.java:1203)
        at org.apache.pdfbox.cos.COSStream.accept(COSStream.java:388)
        at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObject(COSWriter.java:522)
        at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObjects(COSWriter.java:460)
        at org.apache.pdfbox.pdfwriter.COSWriter.doWriteBody(COSWriter.java:444)
        at org.apache.pdfbox.pdfwriter.COSWriter.visitFromDocument(COSWriter.java:1099)
        at org.apache.pdfbox.cos.COSDocument.accept(COSDocument.java:419)
        at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1370)
        at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1257)
        at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1278)*

Any help is greatly appreciated

Alexey Subach
  • 11,903
  • 7
  • 34
  • 60
moyez
  • 59
  • 8
  • 1
    I don't know much about xfa, but please try this: 1) create your COSStream with `document.getDocument().createCOSStream()`, 2) take care to close your `cosout.createOutputStream()` object after done, 3) close `fos` when done or save directly into a file. – Tilman Hausherr Oct 27 '17 at 21:12
  • Write the transformation result to an intermediate storage such as a `File` or `byte[]` and then read that into the COSStream as it can either be open for writing or reading. – Maruan Sahyoun Oct 28 '17 at 09:24

1 Answers1

2

I resolved this with document.getDocument().createCOSStream(), as Tilman Hausherr suggested and closing the created outputstream after setting the XFA resource, the code looks like this

COSStream cs = doc.getDocument().createCOSStream();
OutputStream os = cs.createOutputStream();

Result outputTarget = new StreamResult(os);
Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(new DOMSource(xmlDoc), outputTarget);

PDXFAResource resout = new PDXFAResource(cs);

aform.setXFA(resout);
os.close();
doc.save( "test.pdf" );
Rob
  • 26,989
  • 16
  • 82
  • 98
moyez
  • 59
  • 8