Mark's Stuff

My Foray Into Weblogging. Using this to store interesting items for later review.

Monday, June 15, 2009

Interesting problem: IIS file download = 0 bytes

I ran into an interesting problem at a client site the other day.  Another developer group had written and installed a ASP.Net application (Visual Studio 2008, .Net Framework 3.5 SP1, Windows Server 2003 R2, SQL Server 2005).  Without divulging too many details, let's just say the application had a public site where users could upload a file, and an internal admin site where the internal user could download the file.  The file is being stored in the database in a varbinary(max) column.

After the sites were installed, the internal user had a problem downloading the file; it always came back as 0 bytes.  It did not matter the file type (pdfs and word docs were used), browser type (same for IE6 (standard for company), IE7, IE8, Firefox 3.x, Chrome, Opera , Safari on Windows).  The file was definitely in the database, and the original developer wrote a Windows desktop app to download the file as a temporary workaround.  The original developer swore the file download it worked just fine on their servers, and brought in a more experienced consultant to try to help diagnose the problem.  I was at this client site on another project, and was asked to take a look to see if I could spot anything.

After a few false starts doing some troubleshooting (the original developer said the VS project was a web site project, and had the code-behind files in the web directory, so we would modify the .cs file to try to track the problem, but had no results; turns out it was a web application project, and we were not recompiling the project), we did confirm the byte array from the database field was being populated.  The code was using Response.BinaryWrite, and seemed to be setting the proper headers and sending the data.  We look at the IIS web site settings over and over, trying to find some clue. 

The server the web application was installed on did have other live applications running, so our debugging the production server was limited so as to not affect the other apps. Our next attempt was to setup another Windows IIS server (virtual, on MS Virtual Server) and install the web site app on there.  The file download worked just fine there.  So it appears that the application is OK, it must be an IIS setting causing the problem.  Now that we had a server we knew it worked on, I took the metabase.xml files from both servers and worked to compare them.

That was when I saw the problem: HTTP Compression was turned on the first server.  We had missed it on the IIS Settings because that (the "Service" tab) is only on the property dialog for the Web Sites folder, not on the web sites themselves, and not on the server settings.  Here is the dialog window:

clip_image002

Turning that off did solve the download file problem, but the client was uneasy about turning it off (understandably) since it was likely turned as part of the other applications that was running on that server, and they did not want to risk that apps.

Although I knew it would not affect the other apps to turn off HTTP compression, I looked further into it and saw that HTTP compression can be turned on or off for the entire server, by web site, by directory, by file type, or by individual page, all by using adsutil commands.  I also found a .cmd file in the AdminScript directory of the server turning on HTTP compression, so I modified it to turn off compression for the web site:

CSCRIPT.EXE ADSUTIL.VBS SET W3SVC/Filters/Compression/GZIP/HcScriptFileExtensions "asp" "dll" "exe" "pdf" "aspx" "svc"
CSCRIPT.EXE ADSUTIL.VBS SET W3SVC/Filters/Compression/DEFLATE/HcScriptFileExtensions "asp" "dll" "exe" "pdf" "aspx" "svc"
CSCRIPT.EXE ADSUTIL.VBS SET W3SVC/Filters/Compression/GZIP/HcDynamicCompressionLevel 9
CSCRIPT.EXE ADSUTIL.VBS SET W3SVC/Filters/Compression/DEFLATE/HcDynamicCompressionLevel 9
CSCRIPT.EXE ADSUTIL.VBS SET W3SVC/Filters/Compression/GZIP/HcStaticCompressionLevel 9
CSCRIPT.EXE ADSUTIL.VBS SET W3SVC/Filters/Compression/DEFLATE/HcStaticCompressionLevel 9
CSCRIPT.EXE ADSUTIL.VBS SET w3SVC/Filters/Compression/Parameters/HcDoDynamicCompression true 
CSCRIPT.EXE ADSUTIL.VBS SET w3SVC/Filters/Compression/Parameters/HcDoStaticCompression true 
REM Added exclusion for careeradmin site; mark harr; 6/3/2009
CSCRIPT.EXE ADSUTIL.VBS SET W3SVC/2129524648/root/DoDynamicCompression false

That solved the issue.  But there were a couple other interesting things:



  • I first looked to turn off compression for just the file types (pdf, etc), but it turns out that IIS determines if compression will be done based on the requested file suffix, not the response headers. So since the file was downloaded from a postback to index.aspx, turning off compression on pdf did not have any affect.

  • Then I looked to turn off just for the page doing the download. But since the site was built with a single page (index.aspx) and loading different custom controls (ascx), I could not differentiate the page for IIS.

  • So I just turned off http compression for the admin site.  Figure that was not bad, since the site will only be accessed internally, and not likely over the internet, the lack of http compression will not be an issue.

  • After I finished this, I came up with the thought that perhaps adding a "Response-encoding: gzip" header with the file download may have also solved the problem.  IIS may have already setup that header when it determined it was doing http compression, and the code may have been clearing that header when it did the Response.Clear command before setting up its BinaryWrite.  But the code putting that header would need to ensure that compression was happening and only add the encoding header when desired.  Sometime when I have a few hours to look at that, I will see if that technique will work.

Labels: , ,

2 Comments:

  • At 8/24/2009 3:45 PM , Blogger Mandi said...

    I've been trying to solve this problem, as I have recently implemented http dynamic compression. The download of pdf and docx files is interrrupted. PDF files shouldn't be on the compression list anyway (which they are not on our servers)) since they are already compressed, but there still seems to be an issue when you try to download/load these docs from the dynamic sites.

    Once compression on dynamic files was turned off, the downloads worked again. The filetypes we had listed were; dll (known to be an issue) asp asmx aspx exe axd.

    I am guessing it's having "dll" in the mix that is causing the issues, but cannot test it at the moment, so as to keep our clients form yelling. The sites may be a bit slow, but at least they function properly.

    Let me know if you find an answer!

     
  • At 10/24/2009 9:52 AM , Anonymous Anonymous said...

    Ran into a similar problem myself when compression is on for aspx pages and if the page was rendering mime type pdf then browser was not rendering the pdf content and just indicated it received the headers.

    Through some debugging found out that the culprit was response.close(). Once I removed that the file pdf content was downloading fine.

     

Post a Comment

Subscribe to Post Comments [Atom]

Links to this post:

Create a Link

<< Home