streaming pdf fails - file not found
I spent some time this morning trying to help a colleague with an odd bug that currently has three of us stumped. The scenario is that we have a system under development which allows users to attach pdf files to a data record. The system uses a service to store and retrieve the files from a server and stores an identifier in an attachments table to indicate which files belong to which records.
Then, on two different pages within the app, we have a grid which displays the list of attachments for a record. Within the grid are link buttons which allow a user to open a given attachment. The link button raises a command event passing the identifier of the attachment as its argument. In the command event handler we grab the identifier from the argument, use it to retrieve the attachment from the service in the form of a byte array, and then override the response object to return the attachment. Here is the code:
byte[] byteFile = DataHandler.GetAttachmentDocument(selectedAttachmentID);
if (DataHandler.sErrorMsg != "")
{//Error trying to retrieve file...
this.DisplayMessageBox(DataHandler.sErrorMsg);
}
else
{//File retrieved...
Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=" + lblAttachmentName.Text);
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.BinaryWrite(byteFile);
Response.Flush();
Response.Close();
Response.End();
}
Now this exact same code works perfectly on one page and fails on the other. In both cases when a button is clicked and a download dialog displays, click the open button and an adobe reader window opens. On the working page the reader window displays the requested document, but on the other page we get an error from the reader window stating: There was an error opening this document. This file cannot be found.
Running in the debugger we can step through and see that we are getting the same number of bytes in byteFile, and that we are stepping through the full method without errors.
We have googled quite a bit on this and tried several variation to this code without having any luck. A couple of things I know we tried were changing the co开发者_高级运维ntent type to an octet stream, adding the content length to the header, changing the buffer to false, removing the content disposition attribute. The only one that made a noticeable difference was removing the content disposition attribute, in that case the document displayed but it showed up in the original window, not a separate adobe reader window. One other idea which was proposed but not tried so far, would be to extract the grid and associated logic out to a web control which could then be reused on both pages. Any other suggestions?
Don't use Response.Close() and Response.End(). Flush() is enough.
Here's why: http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx
While we never were able to work out exactly what was causing the problem, we did determine that it was at least somewhat user/machine specific. So our best guess is some sort of odd conflict, or caching issue, on the client side.
What we ended up doing as a work around was developing a blank page which accepts the attachment ID and name on the query string, performs some security checks, and then returns the requested attachment. This gave us a single, reusable, module containing our attachment retrieval code.
We then went into the pages that serve up the attachments and changed our grid templates from link buttons with command arguments to hyper links with a navigate URL bound to the path of the new page + query string arguments and a target of _blank
.
The end result is that we eliminated the errors without major changes to the page structure, maintained the desired end user experience, and have a code structure that is going to be easier to maintain.
Thanks to Leon for the tip. While it did not fix the problem, it did help us clean up our code a bit.
精彩评论