views:

985

answers:

2

Hello,

Let's say I have a pdf form file available at website which is filled by the users and submitted to the server. On the server side (Asp.Net) I would like to merge the data that I receive in xml format with the empty pdf form that was filled and save it.

As I have found there are several possible ways of doing it:

  1. Using pdf form created by adobe acrobat and filling it with itextsharp.
  2. Using pdf form created by adobe acrobat and filling it with FDF Toolkit .net (which seems to be using itextsharp internally)
  3. Usd pdfkt to fill the form.
  4. Use pdf form file created with adobe livecycle and merge the data by using Form Data Integration Service

As I have no experience with this kind of task can you advise which option would be better/easier and give some additional tips?

Thank you in advance.

A: 

Since you tagged this 'LiveCycle', I take it you have an installation of Adobe LiveCycle running somewhere (optionally, can install it somewhere).

In that case, I'd go for number 4 (with the modification of using the Adobe LiveCycle Forms ES module). The other three will undoubtedly yield compatibility issues in the long run. With the LiveCycle server (running the Forms module), you'll be able to handle any PDF, whether it's old, new, static, dynamic, compressed, Acrobat-based or LiveCycle-based.

You should be able to set things up, have the form send its data to the LiveCycle server, and use that data to populate the form. The fill can then be stored in the server's database, or routed into the PDF form (or any other form) and streamed back to the client.

Create the form using LiveCycle Designer.

The quick-and-dirty-option would be the following: Set the form to http-post (as for example an xfdf, see Acrobat for more info) to your ASP-server and publish it on the server (make sure your users don't download the form before opening it, otherwise this won't work. The form has to be opened in the web browser). Then simply capture the submissions as you would capture a http-post from a web page. Optionally, save the fill to a database. Then send the captured xfdf stream fill back to the client (could also be invoked at a later stage via a http-link). The xfdf stream will contain the URL of the form used to fill it out. The client web browser will ask the Acrobat/Adobe reader plug to handle the xfdf stream, and the plug will locate, download and populate the form pointed to by the xfdf.

The user should now be able to save the form AND it's fill - no Reader Extension needed!

paque
@Christian - I need to save the pdf file on the server, not at the user side.
Giorgi
+2  A: 

I would suggest using the 4th approach if possible because it would be cleaner. You would be using solutions specifically tailored for what you are asking to do, but if you don't have the available resources for such a solution I would suggest using the 1st option.

The 1st option is what I have recently dove into. I have found it relatively painless to implement.

Option 1 is possible if the following applies:

  1. You have control of development of PDF forms.
  2. You have control of formating xml data
  3. You have can live with having uncompressed (fastweb=false) PDF files

Example of implementation:

  1. Using Adobe Acrobat to generate a PDF form. Tip: Use Adobe Native Fonts when generating the forms. For each control you add that is not a native font it will import the font used and bloat the file when it is not compressed, and to my knowledge ITextSharp currently does not produce compressed PDFs.

  2. Using ITextSharp Library to combine XML data with the PDF form to generate a populated document. Tip: to manually populate a PDF form from xml you must map xml values to control names in the PDF form and match them by page as shown in the example below.

    using (MemoryStream stream = GeneratePDF(m_FormsPath, oXmlData))
    {
          byte[] bytes = stream.ToArray();
          Response.ContentType = "application/pdf";
          Response.BinaryWrite(bytes);
          Response.End();
    }
    
    
    // <summary>
    // This method combines pdf forms with xml data
    // </summary>
    // <param name="m_FormName">pdf form file path</param>
    // <param name="oData">xml dataset</param>
    // <returns>memory stream containing the pdf data</returns>
    private MemoryStream GeneratePDF(string m_FormName, XmlDocument oData)
    {
    PdfReader pdfTemplate;
    PdfStamper stamper;
    PdfReader tempPDF;
    Document doc;
    MemoryStream msTemp;
    PdfWriter pCopy;
    MemoryStream msOutput = new MemoryStream();
    
    
    pdfTemplate = new PdfReader(m_FormName);
    
    
    doc = new Document();
    pCopy = new PdfCopy(doc, msOutput);
    
    
    pCopy.AddViewerPreference(PdfName.PICKTRAYBYPDFSIZE, new PdfBoolean(true));
    pCopy.AddViewerPreference(PdfName.PRINTSCALING, PdfName.NONE);
    
    
    doc.Open();
    
    
    for (int i = 1; i < pdfTemplate.NumberOfPages + 1; i++)
    {
        msTemp = new MemoryStream();
        pdfTemplate = new PdfReader(m_FormName);
    
    
    
    stamper = new PdfStamper(pdfTemplate, msTemp);
    
    
    // map xml values to pdf form controls (element name = control name)
    foreach (XmlElement oElem in oData.SelectNodes("/form/page" + i + "/*"))
    {
        stamper.AcroFields.SetField(oElem.Name, oElem.InnerText);
    }
    
    
    stamper.FormFlattening = true;
    stamper.Close();
    tempPDF = new PdfReader(msTemp.ToArray());
    ((PdfCopy)pCopy).AddPage(pCopy.GetImportedPage(tempPDF, i));
    pCopy.FreeReader(tempPDF);
    
    } doc.Close(); return msOutput; }
  3. Save the File or post the file to the response of your ASP.Net page

Jonathan