IIS HTTP Compression and Streaming PDF's: Don't do it.
It started simple enough. We were generating PDF’s to stream down to the a browser. Everything worked fine in development. We moved the release to our staging environment, which mirrors our production environment.
No PDF’s. Just a blank Acrobat window.
Ok, first things first: what’s different? Ah HA, staging has SSL enabled. Ok, quick run through to enable SSL on our development environment should let us know what the problem was. Except that wasn’t it. We enabled SSL and everything still worked. There’s even a well known bug in IE with regards to Office documents & SSL. But our site wasn’t working in FireFox either.
We were stumped. Then someone says “Let’s look at the Response Headers”. Brilliant. What do we find? GZIP. “Oh, yeah, BTW, we have HTTP compression enabled in prod / staging” someone says. Damn. Corruption and Compression both start the same way, after all. This makes sense because we were still getting PDF’s. They were just corrupted. We figured that the browser was trying to pass the PDF to Acrobat BEFORE decompressing it, which would make Acrobat bomb out.
Quick trip to google to see how to enable HTTP Compression on our development environments revels that, well, you can’t. HTTP Compression isn’t available on Windows XP. Ok, so what now? Google tells us that you can turn compression off for certain files and directories, but we don’t want to take a drastic step like that just yet. After all, these PDF’s can be big and compression would help with bandwidth issues. Plus it meant digging in the IIS metabase, and we could figure out a better way right? RIGHT?
Here’s a small list of things we did try, all to no avail:
1. Change MIME type from application/pdf to application/octet-stream.
2. Explicitly set the content parameters on the response headers ( Length, etc.. )
3. Move from using Response.WriteFile to writing the explicit byte array to the Response output stream
4. Changing the casing of the variables we were setting in the response headers ( Content-Type vs. content-type )
5. Alter the Content-Disposition header
6. Flush the Response before sending the file only
7. Flush the Response after sending the file.
8. Flush the Response before and after sending the file.
9. Alter how we were generating PDF’s ( using different PDF generation libraries )
As you can see from the list above, we were desperate. We were just about to bring out the live chickens to sacrifice, when I tried to disable HTTP 1.1 in Internet Explorer, which would disable HTTP Compression support.
Bingo. There’s a day i’d like back. So, it seems, we have to disable compression on pages serving up PDF content. Of course, this is what we expected and knew we could do if we wanted to, but we were smart guys right? We could figure it out right? The moral of the story? Sometimes the simplest answer is really the right answer.
However, we didn’t want to have to go into the metabase every time we added a page that shouldn’t have compression turned on, so we created a single directory that will hold our non-compressed pages. Then, we simply turned off compression for that directory. This took no more than 10 minutes, and most of that was creating the directory and moving the pages.