michael orlitzky

Streaming Files to Internet Explorer over HTTPS

So, I wasted a few hours trying to figure out how to get Internet Explorer to accept a streaming file download over HTTPS. It turns out (surfuckingprise) that this is a known bug in Internet Explorer. The KB article claims that this only affects IE6 SP1 and below; but I assure you, it affects the very newest version of IE7.

In particular, the KB article states:

This issue occurs if the server sends a "Cache-control:no-store" header or sends a "Cache-control:no-cache" header.

So why did I spend so much time on this? Well, because the KB article is wrong. Not only does it fail to mention that the problem exists in IE7, it leaves out one important cause of the problem. In hindsight, I should have read the entire HTTP spec, so that I could know by heart which parts Microsoft has decided to ignore.

Gentlemen, meet the HTTP Pragma header. Apparently, the Pragma header allows the specification of some optional behaviors in order to maintain backwards-compatibility with non-HTTP/1.1 clients. Awesome! Except Internet Explorer overrides the value of your Cache-control header with the value of the Pragma header.

If you haven't gotten the idea by now, the web server was returning both a Cache-control and a Pragma header. The Cache-control header did not specify no-cache. The Pragma header, however, did. From whence the Pragma header came is something of a mystery. These are the headers that don't work:

1
2
3
4
5
6
7
8
9
10
11
HTTP/1.x 200 OK
Date: Thu, 24 Apr 2008 03:43:26 GMT
Server: Apache
Expires: 0
Cache-Control: private, must-revalidate
Pragma: no-cache
Content-disposition: attachment; filename=attendee_list.xls
Content-Length: 3556
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: application/vnd.ms-excel

The solution, of course, is to override the Pragma header as well. It's not that big of a deal once you figure out that there's a second bug. Want to add that to the KB article, fuckers? Here's the (PHP) code I used to send the headers that ultimately worked:

1
2
3
4
5
header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition: attachment; filename={$filename}");
header('Expires: 0');
header('Cache-Control: private, must-revalidate');
header('Pragma: private');

If anyone's counting, Microsoft just cost the economy about $450.00.