6

I'm using iTextSharp 5.3.2.0 to add information to an existing PDF file that contains a W-2 form. Everything is working perfectly and the PDF file looks great when written into the browser's response stream; however, when the user is done looking at the PDF, he is asked "Do you want to save changes to 'W2.pdf' before closing?" every time he views the document from the web page.

In trying to narrow the problem down, I've actually stripped out all of my modifications but the problem continues. Here's the simple version of my code, with my data-writing call commented out:

PdfReader pdfReader = new PdfReader(dataSource.ReportTemplate);

using(MemoryStream outputStream = new MemoryStream())
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream))
{
   //dataSource.DrawDataFields(pdfStamper);
   pdfStamper.FormFlattening = true;
   return outputStream;
}

In this case, the "empty" PDF is written to the browser and looks good, but I still get asked, "Do you want to save" when I close the Acrobat window.

At this point I was thinking that there was something wrong with the source PDF file. However, when I send back the PDF file's raw bytes to the browser, I am NOT asked the "Do you want to save" question when using the code below.

byte[] bytes = File.ReadAllBytes(dataSource.ReportTemplate);

using (MemoryStream outputStream = new MemoryStream())
{
    outputStream.Write(bytes, 0, bytes.Length);
    return outputStream;
}

My conclusion is that iTextSharp is doing something "bad" to the PDF in the process of opening it and writing the bytes to the stream, but I'm new to iTextSharp and could easily be missing something.

FWIW, this is Acobat Reader 10.1.4 that we're talking about.

EDIT: The original PDF used as a template is approximately 80K in size. If I look at the temporary file that's been streamed down through my browser, the PDF file written by iTextSharp is approximately 150K. However, when I answer "Yes" to the "Save Changes" question asked by Acrobat Reader, the resulting file is approximately 80K again. iTextSharp is definitely doing something unexpected to this file.

marc
  • 3,248
  • 4
  • 28
  • 33
  • possible duplicate: http://stackoverflow.com/questions/2186817/itextsharp-filestream-corrupt-pdf-file – VahidN Sep 25 '12 at 05:28
  • Certainly a duplicate with http://thread.gmane.org/gmane.comp.java.lib.itext.general/63197 – Bruno Lowagie Sep 25 '12 at 10:02
  • IMO, this is a different issue than the one linked to by VahidN - notice that I'm reading in an existing PDF file, then writing text over it. But even if I comment out my text-writing code, the problem occurs. – marc Sep 25 '12 at 15:04

2 Answers2

15

Non-working:

public byte[] MergeDataByDrawing(int copies)
{
    PdfReader pdfReader = new PdfReader(reportTemplate);

    using (MemoryStream outputStream = new MemoryStream())
    using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream))
    {
        pdfStamper.FormFlattening = true;
        return outputStream.GetBuffer();
    }
} 

Working:

public byte[] MergeDataByDrawing(int copies)
{
    PdfReader pdfReader = new PdfReader(reportTemplate);

    using (MemoryStream outputStream = new MemoryStream())
    using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream))
    {
        pdfStamper.FormFlattening = true;
        return outputStream.ToArray();
    }
}

Seems the GetBuffer method is a problem. I don't understand why, but I'll take the result!

Props to MKL for giving me an idea and Fredrik for the right example at the right time.

marc
  • 3,248
  • 4
  • 28
  • 33
  • 2
    `MemoryStream.GetBuffer()` may add garbage to the actual data contained in the stream. [See the documentation](http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx). So when working with iTextSharp always call `ToArray()` instead. – kuujinbo Sep 26 '12 at 03:32
  • 2
    A PDF is read from bottom to top. A PDF Reader expects the final bytes to be `%%EOF`. If other bytes are added after the final occurrence of `%%EOF`, some readers will try to fix this. Does `ToArray()` fix your problem? In that case, it's not necessary to send me the PDF. To make sure you've got the correct solution, you could compare the number of bytes produced by `GetBuffer()` vs `ToArray()`. If the `ToArray()` generates less bytes, you've solved the problem. – Bruno Lowagie Sep 26 '12 at 06:03
  • Yes, ToArray() nearly halved the number of bytes being returned and presto!, all was well. – marc Sep 26 '12 at 21:12
  • is there a similar fix for Android/Java? – George Nov 15 '13 at 17:45
1

See http://itextpdf.com/history/?branch=52&node=521

Bugfix AcroForms: In some cases, Adobe Reader X asks if you want to "save changes" after closing a flattened PDF form. This was due to the presence of some unnecessary entries in the /AcroForm dictionary (for instance added when the form was created with OOo).

I'm the Bruno who fixed this bug. I remember that it occurred in Adobe Reader 10, but not in Adobe Reader 9. I was able to fix the bug because the person reporting it was a customer who sent me a PDF that showed this behavior.

If you would share your PDF, we could take a look and see what other entries should be removed from the /AcroForm dictionary. I only removed those that were added when the form is created using Open Office. If you don't want to share the PDF, the cause will always remain a mystery.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • I am eager to share my PDF - how shall I get it to you? I will say that I tried to do a "pdfReader.Catalog.Remove(PdfName.ACROFORM)", but that had no effect. – marc Sep 25 '12 at 16:40