views:

180

answers:

1

In an ASP.NET application, I'm using iTextSharp (PdfStamper, mostly) to fill in some content on a PDF and send it to the user. The following code is inside an OnClick event:

PdfReader r = new PdfReader(
  new RandomAccessFileOrArray(Request.MapPath(compatiblePdf)), null
);

ps = new PdfStamper(r, Response.OutputStream);
AcroFields af = ps.AcroFields;

af.SetField("ContactInfo[0]", o.mallName);
af.SetField("ClientName", string.Format("{0} {1}", c.firstName, c.lastName));
af.SetField("ClientEmail", c.emailAddress);
ps.FormFlattening = true;
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=Form.pdf");
ps.Close();
Response.End();

So, basically, PdfReader gets the file, PdfStamper takes the PdfReader as an argument, and will push its finished PDF to Response.OutputStream.

The problem is that, with IE and Adobe Reader, if you select "Open" from the file dialog, Adobe Reader throws an error saying "file could not be found". Users can "Save" the file just fine, and even starting the download again (clicking "Open" again when asked) seems to work. But on a new machine that's never downloaded the file, Adobe Reader seems to misplace the file between it going to the Temporary Files or whatever IE does.

I can only imagine one thing right now: Response.End(), should, maybe, be Response.Close() instead, or maybe the whole thing should have Response.Flush() before it. But I don't know for sure that that won't make the problem worse, and I'm having a hard time testing (because, once you've downloaded the file once, the error isn't thrown again).

Might that fix the problem? Do I have something wrong in the headers? Or is there something else I should be doing with the Response / PdfStamper objects?

+2  A: 

Whenever I force content at a user, I follow this set of steps for the Response:

Response.Clear()
Response.ClearHeaders()
Response.Buffer = True
Response.ContentType = "your mime type"
Response.CacheControl = "public"
Response.AddHeader("Pragma", "public")
Response.AddHeader("Expires", "0")
Response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0")
Response.AddHeader("Content-Description", "Description of your content")
Response.AddHeader("Content-Disposition", "attachment; filename=""somefile.pdf""")

' Add your content to the buffer here

Response.Flush()
Response.End()

This seems to be pretty good at preventing all the "file not found" garbage.

Cory Larson