Bug downloading file from IIS through ASP.NET

Ok.  So this wasn't a bug in either IIS or ASP.NET...it was a bug in my code. 

The ASP.NET page reads a PDF file from the disk into a byte array (byte[]) and then squirts it out through the HttpResponse using BinaryWrite().  Here's the code...

private void WriteRequestedDocumentToResponse(string filename)
{
     Response.AddHeader(
"Content-Disposition", “attachment;filename=" + filename); Response.BinaryWrite(GetFileAsByteArray(pathToFile)); }

This code has been in production and working for a few weeks and then yesterday the client posted a new version of the PDF file and all of a sudden Acrobat started saying “There was an error opening this document.  The file is damaged and could not be repaired.“  My first instinct was to say “well, the pdf's messed up“ but when the file got downloaded and saved to my local disk, it kept coming out about 1kb bigger than it was supposed to be. 

My second thought was to suspect the GetFileAsByteArray() method even though that method had been used in a bunch of different projects without incident. 

private byte[] GetFileAsByteArray(string fileName)
{
     FileStream fs;
     fs=File.Open(fileName, FileMode.Open, FileAccess.Read);
     byte[] buffer=new byte[fs.Length];
     fs.Read(buffer, 0, System.Convert.ToInt32(fs.Length));
     fs.Close();
     return buffer;
}

So, looking at the GetFileAsByteArray() method, had a moment of panic looking at the Convert.ToInt32 line.  I'm like, “oh...dammit! fs.Length is a 'long' and fs.Read() is changing that value to an int.  Crap!  It's trimming a bunch of stuff because the int value is maxxing out.  After checking what the max value of an Int32 is and running some unit tests, well, let's just say that that turned out to be utter foolishness on my part.  This code will support files bigger than 2GB.  Well, this method checks out. 

So, what about those extra bytes that sometimes get tagged onto the downloaded PDFs?  I opened up the non-corrupted raw PDF data using Visual Studio and scrolled to the end.

Here are the last 10 lines of the good file.

0000220704 00000 n
0000220739 00000 n
0000220763 00000 n
0000220848 00000 n
0000224467 00000 n
trailer
<>
startxref
116
%%EOF

Looks pretty normal and the PDF standard is even nice enough to put an explicit EOF into the file. 

And now the corrupted file... 

AH!  Now, is it totally obvious what's wrong?  After I write the file out to the HttpResponse, the ASP.NET page continues to be rendered.  BAH!

So, the solution is to add a call to Response.End() right after the BinaryWrite() and stop further processing of the ASP.NET page.  Duh!  And I added a Response.Clear() just to make double sure that the response is clean before I start writing the file.

private void WriteRequestedDocumentToResponse(string filename)
{
     Response.Clear();
     Response.AddHeader(
"Content-Disposition", “attachment;filename=" + filename); Response.BinaryWrite(GetFileAsByteArray(pathToFile)); Response.End(); }

So that's that.

-Ben

posted @ Tuesday, August 09, 2005 8:04 AM

Print

Comments on this entry:

# re: Bug downloading file from IIS through ASP.NET

Left by Joshua Bloom at 8/9/2005 1:36 PM
Gravatar
Hey Ben,

You may want to put some error checking in for client disconnects etc.

While dataToRead > 0
' Verify that the client is connected.
If httpContext.Response.IsClientConnected Then
' Read the data in buffer
length = iStream.Read(buffer, 0, 10000)
' Write the data to the current output stream.
httpContext.Response.OutputStream.Write(buffer, 0, length)
' Flush the data to the HTML output.
httpContext.Response.Flush()
ReDim buffer(10000) ' Clear the buffer
dataToRead = dataToRead - length
Else
'prevent infinite loop if user disconnects
dataToRead = -1
End If
End While

Also lets test your vb.net skills and see if you can read this. :)

# re: Bug downloading file from IIS through ASP.NET

Left by Anna at 7/10/2006 4:08 AM
Gravatar
Wow - thanks for posting this! Helped me solve a problem that was driving me nuts...

# re: Bug downloading file from IIS through ASP.NET

Left by Kelvin at 9/2/2006 3:13 AM
Gravatar
Hi, you are a good man. Thank you very much.

# re: Bug downloading file from IIS through ASP.NET

Left by Paul at 9/22/2006 2:43 AM
Gravatar
Awesome find. This might have just inspired me to create my own blog so others can learn from my learning experiences as well. Ohh and just a little advice. Put yourself some google Adsense on your blog. Developers like me would be more than happy to click on your ads when you hold the solution to our problem.

# re: Bug downloading file from IIS through ASP.NET

Left by Duane at 10/2/2006 2:51 PM
Gravatar
Ben,

I have a problem with your solution. I have been working on an app where we were writing out a PDF to the Response object just like you are doing. The only difference was that we're getting the PDF data from ReportServer.

We were using the Response.End method from the beginning. We found that the Response.End method causes the ThreadAbortException (http://support.microsoft.com/kb/312629/EN-US/). I found that this was caused the Application process to restart and cached controls to refresh unnecessarily. So we took the advice of Microsoft and started using the CompleteRequest method.

All was fine until users experienced the PDF error as mentioned in your blog. Now I'm stuck because both solutions cause problems.

Any help would be cool.

Duane

# re: Bug downloading file from IIS through ASP.NET

Left by Auckland travel guide at 11/28/2007 3:05 PM
Gravatar
i try to find it in the microsoft website
but i didnt find it yet

# re: Bug downloading file from IIS through ASP.NET

Left by oyunlar at 11/29/2007 2:25 PM
Gravatar
htanks

# re: Bug downloading file from IIS through ASP.NET

Left by dang at 1/8/2008 9:19 PM
Gravatar
cheers mate, solved my issues. your a champ!

# re: Bug downloading file from IIS through ASP.NET

Left by מתקנים מתנפחים at 2/6/2008 9:23 AM
Gravatar
that's why i don't like microsoft

# re: Bug downloading file from IIS through ASP.NET

Left by מצלמות אבטחה at 5/3/2008 11:37 AM
Gravatar
Thank you very much for posting this!

# re: Bug downloading file from IIS through ASP.NET

Left by Kevin Shoaff at 5/15/2009 4:40 PM
Gravatar
Thanks for posting this. I've been trying all kinds of different approaches, and this worked easy.

# re: Bug downloading file from IIS through ASP.NET

Left by Hanna at 2/11/2010 11:40 AM
Gravatar
Any one can solve Duane's problem? I have the same problem with Duane's. Response.End() causes the ThreadAbortException and ApplicationInstance.CompleteRequest() causes Ben's problem.

Help please.

Your comment:



 (will not be displayed)


 
 
 
Please add 8 and 1 and type the answer here:
 

Live Comment Preview:

 
«March»
SunMonTueWedThuFriSat
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910