I have an application that I'm using the populate a pdf form using iTextSharp.
/// <summary>
/// Imports XFA Data into a new PDF file.
/// </summary>
/// <param name="pdfTemplate">A PDF File with an unpopulated form.</param>
/// <param name="xmlFormData">XFA form data in XML format.</param>
/// <returns>a memorystream containing the new PDF file.</returns>
public static void XFAImport(System.IO.Stream pdfTemplate, System.IO.Stream xmlFormData, System.IO.Stream outputStream)
{
using (iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(pdfTemplate))
{
using (iTextSharp.text.pdf.PdfStamper stamper = new iTextSharp.text.pdf.PdfStamper(reader, outputStream))
{
stamper.Writer.CloseStream = false;
stamper.AcroFields.Xfa.FillXfaForm(xmlFormData);
}
}
}
The above code takes a pdf form that is not filled out and xml data and writes to the outputStream which is then saved to a file.
When you open the file in Adobe you see the form data filled out correctly. However if you then save that file from Acrobat XI, and then reopen it, the data that you imported is no longer visible.
I don't believe the problem is with the XML that I am importing, because if instead of using iTextShart, I instead use Acrobat XI's "tools/form/more form options/import data". The resulting file is able to be saved and reopened correctly.
My question is:
Am I using the PdfStamper correctly above?
Are there any steps I can take to make the resulting file save correctly?
PS. I've noticed that after resaving the output pdf file using Acrobat XI that the resulting file is mostly identical to the original, however it has an additional 11k of data inserted at the end.
end of the output pdf file:
trailer
<</Size 51/Root 14 0 R/Info 3 0 R/ID [<56549fdaf0c5ab4e9321d77f406e6455><5b60738018e0cdac94c6d1b924fc8bed>]>>
%iText-5.4.4
startxref
529008
%%EOF
After saving in Acrobat XI is has more data added to it:
trailer
<</Size 51/Root 14 0 R/Info 3 0 R/ID [<56549fdaf0c5ab4e9321d77f406e6455> <5b60738018e0cdac94c6d1b924fc8bed>]>>
%iText-5.4.4
startxref
529008
%%EOF
3 0 obj
<</CreationDate(D:20100120124725-05'00')/Creator(Adobe LiveCycle Designer ES 8.2)/ModDate(D:20140221145558-06'00')/Producer(Adobe LiveCycle Designer ES 8.2; modified using iTextSharp’ 5.4.4 ©2000-2013 1T3XT BVBA \(AGPL-version\))>>
endobj
4 0 obj
<</Length 3261/Subtype/XML/Type/Metadata>>stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
/*more data excluded*/
No, you are not using
PdfStamper
correctly.Reader enabling is achieved using a digital signature (it requires a private key from Adobe). When you fill out the form using the "standard way", you break that signature. You need to fill out the form in append mode.
I've explained this in section 8.7.2 of my book, entitled "Filling out Reader-enabled forms using iText" (it beats me why nobody ever reads the documentation before asking a question; one wonders why one even bothers writing a book). You can find the example that comes with this section here: ReaderEnabledForm
You can find the C# version in of the corresponding chapter on SourceForge:
Bottom line: you need to replace
with
In this case, your changes will be appended after the
%%EOF
marker and the digital signature applied by Adobe won't be broken.Actually, the code above caused some problems for people who needed to enter data in the form manually AFTER we populated part of it programmatically. Our XFA form has some 10 steps, where we populate only the first 2 steps. People trying to digitally sign later steps saw an error message, stating "dataModel does not have a method 'clone'." Anyhow, we ended up populating the form fields directly, skipping the need to use an external XML. This solved our problems.
Thanks for the tips. This is what we ended up doing (VB.NET):