Last post Jan 28, 2006 09:59 AM by imagemaker
Jan 25, 2006 10:53 PM|imagemaker|LINK
Here's a really strange case: I'm in the final stages of testing a DNN 3.1 custom module which can generate a PDF report (using iTextSharp as its PDF writing engine) on the fly and then stream it on the Response object. After setting report filters, the
user clicks on "Make PDF" button, then is prompted with the standard message - "Do wish to open or save the file". If he clicks on Open, Adobe Reader opens in a new window and displays the generated PDF document. If he clicks on Save, the file is saved to
the specified path. All, pretty much standard behavior.
HOWEVER, if the user has logged in (been authenticated), when he clicks on Open, he is presented with the error message - "There was an error opening this document. The file cannot be found" then after closing the error an empty Adobe Reader window. He
the authenticated user clicks Save, the PDF file is saved and can later be opened without problem. I know that the PDF generation is working; examination of the Response header shows the proper meta-tag information is being applied; the filename and size
information in the Open or Save dialog is being properly shown.
I found in the forums several threads mentioning similar problems with streaming a file or image in DNN when the user was authenticated. Possible causes mentioned were Url rewriting/Friendly URLS and conflicts with the DNN scheduler HTTP module. No definitive
answers were given. Disabling Friendly URLs and disabling all scheduled events seemed to make no difference - problem still occured when user was logged in then disappeared when user logged off.
Has anyone else experienced this problem. And if so, has a solution been found?
Here's my code for streaming the generated PDF on the Response. All pretty standard, but maybe someone can spot a problem:
Public Sub StreamPDF(ByVal Response As System.Web.HttpResponse, ByVal OpenNewWindow As Boolean, ByVal OutputFilePath As String)
If Not Response Is Nothing And Not PDFStream Is Nothing Then
If DocumentIsOpen Then
Dim Buffer As Byte() = CType(PDFStream, MemoryStream).ToArray()
Dim BufLen As Integer = Buffer.Length
If OutputFilePath Is Nothing OrElse OutputFilePath = String.Empty Then
If Title Is Nothing OrElse Title = String.Empty Then
OutputFilePath = "Report.pdf"
OutputFilePath = Title & ".pdf"
If Path.GetExtension(OutputFilePath).ToLower <> ".pdf" Then
OutputFilePath = Path.GetFileNameWithoutExtension(OutputFilePath) & ".pdf"
If OpenNewWindow Then
Response.AppendHeader("content-disposition", "attachment; filename=" & System.Web.HttpUtility.UrlEncode(OutputFilePath))
Response.AppendHeader("content-disposition", "inline; filename=" & System.Web.HttpUtility.UrlEncode(OutputFilePath))
Response.Flush() 'send the header information to the client
Response.OutputStream.Write(Buffer, 0, BufLen)
Jan 26, 2006 12:14 PM|ecktwo|LINK
Try adding after Response.Clear()
Jan 26, 2006 01:01 PM|imagemaker|LINK
Adding Response.ClearHeaders() solved the problem!
I had been under the mistaken impression that Response.Clear() in turn called ClearContents and ClearHeaders, but was wrong. ClearContents actually calls Clear and only clears the HttpWriter's buffer. The difference in behavior between the user being authenticated
or not may stem from there being two additional cookies on the Response header when he/she is authenticated. Response.ClearHeaders, among other things, clears the cookies from the Response.
Thanks for your help!
Jan 28, 2006 09:59 AM|imagemaker|LINK
I guess that I spoke too soon when I thought this solved the problem. While the addition of Response.ClearHeaders() did allow the authenticated user to open the dynamically generated pdf streamed on the Response, I happened to check the DNN log for information
on a different problem and found many of the following General Exceptions:
Server cannot modify cookies after HTTP headers have been sent. at System.Web.HttpResponse.BeforeCookieCollectionChange() . . .
When the user is not authenticated, no exceptions are thrown. When the user is authenticated, the above exception is logged each time a PDF is streamed. I then compared the headers and content of Response just before the PDF is streamed both with and without
the user being authenticated. The primary difference is that when the user is authenticated, a cookie containing his/her roles appears in the Response.Cookies collection. As an experiment, I then changed the following line in Web.Config from . . .
with the result that the exceptions were no longer appearing when the user was authenticated.
Does anyone have any thoughts as to how badly this will impact website performance on a relatively low hit-count site. Without looking in detail at the core code, I'm assuming that without cacheing the
user's roles in a cookie, the DB will have to be hit again for roles information on each page load.
Would it be better to leave cacheRolesInCookie="true" and let the exception be thrown each time an authenticated user creates a PDF?
Ultimately, is this something that needs to be addressed by a core code change?