java - iText Fill Form / Copy Page to new Document -


i'm useing itext fill template pdf contains acroform. want use template create new pdf dynamically pages. idea fill template pdf, copy page written fields , add new file. main problem our customer want designe template them self. i'm not sure if try right way solve problem.

so i've created code don't work right error com.itextpdf.io.ioexception: pdf header not found.

my code

 x = 1; try (pdfdocument finaldoc = new pdfdocument(new pdfwriter("c:\\users\\...final.pdf"))) {         (hashmap<string, string> map : testvalues) {             string path1 = "c:\\users\\.....temp.pdf"             inputstream template = templatevalues.get("template");              pdfwriter writer = new pdfwriter(path1);              try (pdfdocument pdfdoc = new pdfdocument(new pdfreader(template), writer)) {                 pdfacroform form = pdfacroform.getacroform(pdfdoc, true);                 (hashmap.entry<string, string> map2 : map.entryset()) {                      if (form.getfield(map2.getkey()) != null) {                         map<string, pdfformfield> fields = form.getformfields();                         fields.get(map2.getkey()).setvalue(map2.getvalue());                       }                  }             } catch (ioexception | pdfexception ex) {                 system.err.println("ex2: " + ex.getmessage());              }             if (x != 0 && (x % 5) == 0) {                 try (pdfdocument tempdoc = new pdfdocument(new pdfreader(path1))) {                     pdfpage page = tempdoc.getfirstpage();                     finaldoc.addpage(page.copyto(finaldoc));                  } catch (ioexception | pdfexception ex) {                     system.err.println("ex3: " + ex.getmessage());                  }              }              x++;        }     } catch (ioexception | pdfexception ex) {         system.err.println("ex: " + ex.getmessage());     } 

part 1 - pdf header missing

this appears caused attempting re-read inputstream w/in loop has been read (and, depending on configuration of pdfreader, closed). solving depends on specific type of inputstream being used - if want leave simple inputstream (vs. more specific yet more capable inputstream type) you'll need first slurp bytes stream memory (e.g. bytearrayoutputstream) create pdfreaders based on bytes.

i.e.

bytearrayoutputstream templatebuffer = new bytearrayoutputstream(); while ((int c = template.read()) > 0) templatebuffer.write(c); (/* loop */) {     ...     pdfdocument filledinacroformtemplate = new pdfdocument(new pdfreader(new bytearrayinputstream(templatebuffer.tobytearray())), new pdfwriter(tmp))    ... 

part 2 - other problems

couple of things

  1. make sure grab released 7.0.1 version of itext since included couple of fixes wrt/ acroform handling
  2. you can away using bytearrayoutputstreams temporary pdfs (vs. writing them out files) - i'll use approach in example below
  3. pdfdocument/pdfpage in "kernel" module, yet acroforms in "form" module (meaning pdfpage intentionally unaware of acroforms) - ipdfpageextracopier sortof bridge between modules. in order copy acroforms, need use two-arg copyto() version, passing instance of pdfpageformcopier
  4. field names must unique in document (the "absolute" field name - i'll skip field hierarcies now). since we're looping through , adding fields template multiple times, need come strategy rename fields ensure uniqueness (the current api little bit clunky in area)

    file acroformtemplate = new file("sometemplate.pdf"); map<string, string> somemapoffieldtovalues = new hashmap<>(); try (     pdfdocument  finaloutput = new pdfdocument(new pdfwriter(new fileoutputstream(new file("finaloutput.pdf"))); ) {     (/* looping condition */int x = 0; x < 5; x++) {         // each iteration of loop, create temporary in-memory         // pdf handle form field edits.         bytearrayoutputstream tmp = new bytearrayoutputstream();         try (             pdfdocument filledinacroformtemplate = new pdfdocument(new pdfreader(new fileinputstream(acroformtemplate)), new pdfwriter(tmp));         ) {             pdfacroform acroform = pdfacroform.getacroform(filledinacroformtemplate, true);             (pdfformfield field : acroform.getformfields().values()) {                 if (somemapoffieldtovalues.containskey(field.getfieldname())) {                     field.setvalue(somemapoffieldtovalues.get(field.getfieldname()));                 }             }             // note because we're adding template multiple times             // need adopt field renaming strategy ensure field             // uniqueness in final document.  demonstration's sake             // we'll rename them prefixed w/ our loop counter             list<string> fieldnames = new arraylist<>();             fieldnames.addall(acroform.getformfields().keyset()); // avoid confurrentmodification             (string fieldname : fieldnames) {                 acroform.renamefield(fieldname, x+"_"+fieldname);             }         }          // temp pdf needs "closed" pdf finalization         // magic happen...so open new read-only version act         // source merging our in-memory bucket-o-bytes         try (             pdfdocument readonlyfilledinacroformtemplate = new pdfdocument(new pdfreader(new bytearrayinputstream(tmp.tobytearray())));         ) {             // although pdfpage.copyto work simple pages, pdfdocument.copypagesto             // more comprehensive copy (wider support copying outlines , tagged content)             // it's more suitable general page-copy use.  also, since we're copying acroform             // content, need use pdfpageformcopier             readonlyfilledinacroformtemplate.copypagesto(1, 1, finaloutput, new pdfpageformcopier());         }     } } 

Comments

Popular posts from this blog

angular - Is it possible to get native element for formControl? -

unity3d - Rotate an object to face an opposite direction -

javascript - Why jQuery Select box change event is now working? -