Making IE Accept File Downloads

I’ve been adding more report features to our internal web app at work. Getting them to the point they are at now is another story, for now let me tell the tale of convincing Internet Explorer (IE) to download a comma separated value (CSV) version of these reports. Here is the situation, a secure (SSL) connection to Apache to an internal website written in PHP talking to a PostgreSQL database with IE 6 on the client end. The initial version of the reports just displayed in an HTML table as part of the site. It was suggested that the data should be available as CSV so that employees could easily manipulate or graph the data in Excel. Sounded reasonable enough. After a couple of tries it looked like I had everything working. All of my initial tests were done using Firefox on Windows, with a little bit of testing using Safari on OS X. I know we still have some folks at work who are still using IE (that too is another story) so I tested that one out last. Everything worked, right up until I tried to download the CSV version of the reports.

Instead of prompting me with a dialog box to determine if I wanted to open the file or save, IE simply came back and indicated that it couldn’t save the file and presented with me with one option, ‘OK’. Of course ‘OK’ isn’t really ‘OK’, because it terminated the download and dropped me back into the website. Just great, I thought I was pretty much done and then IE showed its unpleasant side. Knowing that someone else must have ran into this problem I went on a hunt for a solution. After trying out several ideas over a couple of hours I came across the solution. Here is what I believe to be the minimum solution to make IE correctly download a file presented to it from PHP.

First, when talking to IE there is an additional session parameter that must be set for the download to work (this was the last piece of the puzzle that I found). This has to be done before starting the session.

if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {

Once you have built your CSV string and are ready to send it to the browser you’ll need to add a couple of headers first.

header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="report.csv"');

Now that it all seems to be working it doesn’t look very impressive, but it was certainly disappointing to have my initial solution work in Safari, Firefox and Opera but not IE. I hope this saves someone else the hours I spent figuring out why IE hates me.

87 thoughts on “Making IE Accept File Downloads”

  1. Gah! I ended up doing just that a couple of weeks ago. I was writing a Large File Transfer application (in CF, ASP mind you) and IE would just no co-operate with the download, every other browser worked fine.

  2. FAO: Joseph Scott
    Sir, you are a star. It took me ages to find your solution, but it works.
    Now I can anaesthetise my cold with some whiskey and go to bed with the knowledge that I have completed my days work.

  3. Will, glad I could help. What were you searching for? Perhaps I should update the entry to reflect how people are searching for a solution to this problem.

  4. just ran into this today – i’m wrapping up an ecommerce application and i have a .csv export of shipping addresses for nearly-completed orders… worked fine in firefox, and lo and behold, the client complained they couldn’t download the .csv – their browser of choice? IE. (cue sad horn-playing sounds.)

  5. you can get rid of the session_cache_limiter and just change your header to this

    header(“Content-disposition: inline; filename=filename=”report.csv””);

    notice I changed it to “inline” IE needs that.

  6. Hi guys

    I use this to make IE works but no luck:
    header(“Cache-Control: no-store, no-cache, must-revalidate”);
    header(“Cache-Control: post-check=0, pre-check=0”, false);
    header(“Cache-control: private”);
    header(“Pragma: no-cache”);
    header(‘Content-type: application/octet-stream’);
    header(‘Content-Disposition: attachment; filename=”links.csv”‘);
    header(“Content-Length: ” . strlen($content));
    header(“Content-transfer-encoding: binary”);

    What am I possibly doing wrong here.


  7. Thanks to scoutt’s comment and some more searching, the following code worked for me in Firefox and IE:

    header(“Content-type: application/; name=’Excel'”);
    header(“Content-Disposition: attachment; filename=myWorksheet.xls”);
    header(“Expires: 0”); // Optional
    print “$headern$data”;

  8. There is one more piece to the puzzle that no one seems to have mentioned. For MSIE, Under Tools->Internet Options->Advanced (tab), there is a checkbox “Do not save encrypted pages to disk”

    If this is checked, then pages are not cached which can cause similar problems as mentioned in this article. Uncheck the box.

  9. Thanks a million for the solution. I tried, for giggles, the other suggested solutions in the comments of this post; all to no avail. The only way my spreadsheet download worked was with the cache_limiter. You saved me, Joseph. (btw, The tab order is out of whack for the comment fields. Is that intentional?)

  10. Will, glad I could help. What were you searching for? Perhaps I should update the entry to reflect how people are searching for a solution to this problem.

  11. To prevent overly-aggressive caching by IE, I had to use:

    instead of:


  12. This works fine IN IE and save file “Oreilly Php.chm” to my desktop. But after downloading this file i have noticed that the actual size of “Oreilly Php.chm” is 1.5MB and after ckecking the size of downloaded file i.e. “Oreilly Php.chm” i am quite surprise that it was “3Kb” only also i have tried to open that file. But i have got error message “can not open the file:@MIST Store:C:WindowsdesktopOreilly Php.chm”.
    Why this Please Help Me! Or Reply me at “”

  13. I wanted to thank you. I had built an export class several months ago that will allow CSV, HTML, XML, and TAB files. The problem is that everything worked in Firefox. I had a request to make my class “public” and as soon as I did, I got IE’s unhelpful message.

    A quick trip to Google, and 1 search later, found your site. Took all of 5 minutes.

    Life saver!

  14. Hi,
    My web is hosted in a Windows server and I use ASP, instead of PHP. The following code goes well with HTTP, but fails with HTTPS:

    Any suggestion, please?

  15. Mind you, all this isn’t quite enough to get downloads working in IE as of jul 2006.
    What does work is:

    header(‘Content-type: application/octet-stream’);
    header(‘Content-Disposition: attachment; filename=”‘.$fileName.'”‘);
    header(‘Cache-Control: no-store, no-cache, no-transform, must-revalidate, private’);
    header(‘Expires: 0’);

    Never use: header(‘Pragma: no-cache’)
    As IE simply won’t let users download your data.

    But it doesn’t stop there, the combination of HTTPS and sessions requires another tweak
    hinted at above.
    _before_ you issue a session_start() be sure to call this first:

  16. I’ve just experienced similar problems getting a DB-generated CSV file to download in IE. It was within a web application using PHP sessions and I didn’t want to upset any of the session cookie or cache header settings.

    I was able to get things working satisfactorily with the following code:

    header(‘Content-Type: ‘ . $mime_type);
    header(‘Expires: ‘ . gmdate(‘D, d M Y H:i:s’) . ‘ GMT’);
    header(‘Content-Disposition: attachment; filename=”‘ . $filename . ‘”‘);

    if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘MSIE’)) {
    header(‘Cache-Control: must-revalidate, post-check=0, pre-check=0’);
    header(‘Pragma: public’);
    } else {
    header(‘Pragma: no-cache’);

  17. July 31, 2006: Some of the other proposed solutions had issues, but what you need to remember is this:

    The “no-cache” and “no-store” options are telling IE to get rid of the file once it’s been launched in Excel. The problem is that IE doesn’t actually KNOW when Excel launches the file. Since newer versions of Office are slow to start up, the delay isn’t great enough, so by the time Excel is ready to open the file, IE has already deleted it. Joseph’s solution works because the only cache limiter he’s using is “public”. This haunted me for about 3 hours of solid debugging, and left me feeling like an idiot, since I had originally used a different tutorial that used “Pragma: no-cache”. ;)

  18. Great post and discussion. The comments about:

    if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘MSIE’)) {

    helped me in forcing IE to properly display a Word doc (really, an RTF doc) in SSL.

  19. Unfortunately, none of this has helped me with excel files. I have done it at least 30 different ways and each time it works in Firefox but never in IE!! I am about to go absoultely mad!!

    I am using PHP5 on a server runing Apache/2.0.52 (Red Hat). The server is if it helps.

    I have tried unchecking the box in IE that says “Do not save encrypted pages to disk”.

    I have tried using PEAR’s Spreadsheet_Excel_Writer to no avail, even after modifying the headers.

    I have tried echoing, printing, and even fpassthrough, with excel files, CSV files, and tab delimited files trying to get something, anything working with IE.

    I have tried the following code mentioned in other pages:

    if(!strpos(strtolower($_SERVER[‘HTTP_USER_AGENT’]), “msie”) === FALSE)
    header(“HTTP/1.x 205 OK”);
    } else {
    header(“HTTP/1.x 200 OK”);

    While that helps a few things(which I dont really need), it doesnt help the file serving.

    I have also tried a bunch of different combinations of the follwoing headers:

    //various headers from web
    header(“Content-Type: application/”);
    header(‘Content-type: application/octet-stream’);
    header(‘Content-type: application/; name=”Excel”‘);
    header(‘Content-Disposition: attachment; filename=”test.xls”‘);
    header(‘Content-Disposition: attachment; filename=test.xls’);
    header(‘Cache-Control: no-store, no-cache, no-transform, must-revalidate, public’);
    header(“Cache-Control: no-store, no-cache, must-revalidate”);
    header(“Cache-Control: no-cache, cachehack=”.time());
    header(‘Cache-control: private, must-revalidate’);
    header(“Cache-Control: no-store, must-revalidate”);
    header(“Cache-Control: post-check=-1, pre-check=-1”, false);
    header(‘Pragma: private’);
    header(‘Pragma: public’);
    header(‘Expires: 0’);
    header(“Expires: -1”);
    header(“Expires: Mon, 26 Jul 1997 05:00:00 GMT”);
    header(“Last-Modified: ” . gmdate(“D, d M Y H:i:s”) . ” GMT”);

    //headers from Spreadsheet_Excel_Writer
    header(“Content-type: application/”, false);
    header(“Content-Disposition: attachment; filename=”$filename””, false);
    header(“Expires: 0”, false);
    header(“Cache-Control: must-revalidate, post-check=0,pre-check=0”, false);
    header(“Pragma: public”, false);

    Oh yeah. I have been trying those headers with and without both the public and private versions of the following before my session_start() even though I havent been using session variables in my latest test script:

    if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘MSIE’))

    IE has been the bane of my existence for a few months now. If anyone can help I’d appreciate it. That’s awesome the stuff above worked for a lot of you. I wonder if its all about older versions of IE. Speaking of which the verion on my development computer as well as most of the computers around campus are IE 6.0.2900…


  20. Man, thank you thank you…I had a heck of a time finding a solution until I finally stumbled across your page….live saver.

  21. Scott–where have you been for the last 6 hours! I’m so glad I stumbled across your site, because my issues are now solved! You are the MAN!!

  22. Thanks Duncan. Your solution worked for me.

    – php generated xls and doc
    – https site

    Thanks again.


    # Duncan said on July 10th, 2006 at 7:16 pm

    I’ve just experienced similar problems getting a DB-generated CSV file to download in IE. It was within a web application using PHP sessions and I didn’t want to upset any of the session cookie or cache header settings.

    I was able to get things working satisfactorily with the following code:

    header(’Content-Type: ‘ . $mime_type);
    header(’Expires: ‘ . gmdate(’D, d M Y H:i:s’) . ‘ GMT’);
    header(’Content-Disposition: attachment; filename=”‘ . $filename . ‘”‘);

    if(strpos($_SERVER[’HTTP_USER_AGENT’], ‘MSIE’)) {
    header(’Cache-Control: must-revalidate, post-check=0, pre-check=0′);
    header(’Pragma: public’);
    } else {
    header(’Pragma: no-cache’);

  23. I have a similar problem with IE 6.0 where I am using ASP.NET for downloading (using HTTP Headers)

    Response.AddHeader(“Content-Disposition”,”attachment; filename=abc.tif”)

    I works fine about 30% of time, but the remaining time it behaves odd. Sometimes it does not show SAVEAS dialog box, SomeTimes it shows but fails to Show FileSave DialogBox and Some times it does nothing.

    This is a very patchy and un-predictable behaviour.
    Can anyone tell me what the problem might be.

    1. File Size
    2. Some settings on IE or the IIS 6.0 Web server

    It is driving me and our client crazy.

  24. I found this article and it started me down the right path, but was not the definitive answer, so I wanted to share my finding in hopes of helping others. After the fact I was able to recongnize that some of the above posters came to the same conclusions as me, but no one explicitly stated them.

    My environment is SSL, PDF or RTF download, IE6+, my users where getting the “file could not be written to the cache” error.

    This MS KB entry gives the details (and suggests horrible registry hacks)

    I choose a simpler route, I made sure my web application did not send any of the following:

    Pragma: no-cache

    and then make my users have unchecked the “Do not save encrypted pages to disk” in “Internet Options / Advanced” (unchecked _is_ the default setting, but some users have changed it)

  25. Cheers,
    I’m not sure if I’m happy to have found the solution or p1ssed off that I’ve wasted 4 hours of my life because of 3 lines of IE hack. If you’re interested it is still needed in ie 7!

    Right I’m off to find out what the hell a session cache limiter is

  26. Having developed the site mainly in Firefox only to start testing to find that bl00dy IE has a bug – Getting that sicky feeling knowing there’s such a tight deadline.

    All I can say is thanks! This was one of the first pages I came across and it solved it a peach.

    Cheers again.

  27. This is a very useful posting and especially the one that worked for me :

    header(’Content-type: application/octet-stream’);
    header(’Content-Disposition: attachment; filename=”‘.$fileName.’”‘);private’);
    header(’Expires: 0′);


  28. Good God after banging my head against my keyboard for the better part of the day I found this posting.

    Code did the trick

    You saved my melon and my keyboard from a truely horrific end.


  29. I have the same problem, however when i remove session_start(), it works then in IE.

    Seems like session_start does something to the headers, which causes some issues for IE.

  30. Well, I’ve read all the comments and tried all of them on ie7 and nothing works, bill tried the same stuff as me and his is now working, what did you do in the end BILL?????

  31. Im having the same problem but were using and none of the soutions above work for

    Weve tried all but the “session_cache_limiter(”public”);” stuff as i cant seem to find an equivalent in dotnet?

    Please someonw help me im stuff and the deadline ive got is getting nearer and i have no solution as yet…


  32. for: Moustafa Elqabbany

    You are the best!!! Thanks for your help.


    this is the solution for the “new” IE.

  33. I have tried to follow the instructions mentioned above.
    But it does not work properly for https too.
    I find out that the ‘header’ function does not run in https. As I coded it
    header(“Location: xxx.html”);
    which would not redirect by itself.
    I had to change it to javascript (window.location).
    What’s the problem with my server/ my coding?I have tried many different combination of the code mentioned…What should I change in server config or sth else?

    Please help me T.T

    if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘MSIE’))

    header(‘Content-type: application/’);
    header(“Content-Disposition: inline; filename=”xxx.xls”);
    header(‘Expires: 0’, false);
    header(‘Cache-Control: must-revalidate, post-check=0,pre-check=0’);
    header(‘Pragma: public’);

  34. I am having an issue with IE 6 and MS Excel 2000. When I launch the csv file into IE from my jsp for some reason Excel puts all the data into the first column of the excel document showing the commas.

    This WORKS in Excel 2000 with IE6. Its only on a couple workstations in my office. Also, if I ‘Save’ the csv documnet to a know location and then open it with Excel…its parsed into columns just fine so their is something in the way IE and Excel are communicating about the file type that is an issue.

    response.setHeader(“Cache-Control”, “cache”);
    response.setHeader(“Content-Disposition”, “inline; filename=”+csv_filename );

    Has anyone else experienced this?

    Also, you’ll see that I am setting Cache-Control to ‘cache’. If I try to set it to ‘no-cache’, IE will not pickup the ‘filename’ parameter within the Content-Disposition header……similar to mentioned here.

    Thank You

  35. Sorry – I meant to say in the second paragraph ‘This WORKS in Excel 2002 with IE6 and DOES NOT work in Excel 2000’

    very sorry

  36. You can try with this in IE:

    Tools -> Internet Options -> Advanced (tab), checkbox “[x] Do not save encrypted pages to disk” prevented IE from saving the exported file to its browser cache (and consequently from opening it afterwards).

    In my case, unchecking this setting, fixed the problem.



  37. Hi Duncan,
    Thanks a million to you solution.I changed a module in my ERP for excel export.but it was triggering errors in IE.i worked for more than 10 Hours for this problem.But you saved my a lot of time.
    Thanks a lat

  38. @Jon M

    Thanks your solution of:

    header(”Content-type: application/; name=’Excel’”);
    header(”Content-Disposition: attachment; filename=myWorksheet.xls”);
    header(”Expires: 0?); // Optional
    print “$headern$data”;

    works for me using Firefox 2 and IE 7 – thats in PHP over https://


  39. Duncan!

    Your code solved my problem. Thanks!

    if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘MSIE’)) {
    header(’Cache-Control: must-revalidate, post-check=0, pre-check=0?);
    header(’Pragma: public’);
    } else {
    header(’Pragma: no-cache’);

  40. Help, I have IE6 and I have directory browsing turned on so that Logs can get pulled via http://x:8181/LogFiles. I don’t want to have to write .asp to enumerate as that would mean having to add ASP as an allowed extension unnecessariy.

    I see a lot of scripting solutions, but can I manipulate the custom headers in IE to yield the same results for a directory that has Browsing turned on. The file extensions are currently the date in a YYYYMMDD format.



  41. I lost my nervs in a couple of weeks to solve this problem on our website. Great Hint! Thank you so much!
    Now our CSV-download works fine, only inserting these small four lines of code!

  42. Hi,
    I am facing problem while opening a text file using IE6. It gives an error message like “C:Documents and Settings\Local SettingsTemporary Internet FilesContent.IE5\file[1].csv could not be found.

    After doing google I came to know that it is a know issue with IE6 ( ) But mentioned fix did not work in my case. This is how I am setting http header:

    header(“Cache-Control: “);
    header(“Pragma: “);
    header(‘Content-type: application/octet-stream’);
    header(‘Content-Disposition: attachment; filename=”‘ . $file . ‘.txt”‘); //default extension to .txt for easier open)

    But problem still persist. One workaround is to replace a .txt format to .doc / .rtf, In that case I am able to open file using MS word, but issue will be when someone trying to open a file where don’t have MS word.

    Please Help. I also tried with all the combination for header Pragma and Cache-Control mentioned on this page.

  43. Thank you thank you thank you!!!! This saved me a massive headache.. well, I had one starting until I found your helpful article.. your solution worked.
    Gracias merci and danke schoen!!!

  44. Hi,
    I have the problem which is something related to this post.
    I have trying to download the file using the download code.
    It’s work fine in IE7, Mozilla, chrome but it is not works in IE6.
    The most socking thing is , few days ago , it is working in all the browsers, even in IE6. But today i got this error.When I have trying to use IE6 for download it shows the following message:
    “Internet explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later.”
    Can any body help me?


  45. I am running into similar problem and tried all the combination given in this post but alas!
    I have asp page over SSL and trying to generate the CSV file but not working. Any help?
    Response.AddHeader “Pragma: public”
    Response.AddHeader “Cache-Control: no-store, no-cache, no-transform, must-revalidate, private”;
    Response.AddHeader “Title”, “My Report Results”
    Response.ContentType = “text/csv”
    Response.AddHeader “Content-disposition”, “Attachment;filename=Myreport.csv”

  46. thanks for that. additionally the particular IE’s here are only happy if content-type header offers encoding=… as well.

    header(‘Content-type: application/octet-stream; encoding=UTF-8’);

  47. I’m still having trouble after looking through and trying your suggestion and those in the comments. I’m running ASP.NET 2.0, IIS, Win2003.

    I’m generating a CSV file for users to download when they click a button on a page (the page is SiteReports.aspx). Without SSL, it works great in FF and IE7. With SSL (which I need to do), it works great in FF, but in IE7:

    -> If I have ContentType set to ‘application/octet-stream’, I get a file download prompt, but the filename I gave it is replaced with ‘SiteReports_aspx’, with no extension, so if they user chooses ‘open’ from the download prompt, it opens as plain text within IE.
    -> If I have ContentType set to anything else, I get ‘Internet Explorer cannot download SiteReports.aspx from etc…’.

    I don’t understand why it tries to download something with a different filename than the one I specified in Content-Disposition. I’m currently setting up my headers like this:

    Response.Charset = String.Empty;
    Response.ContentType = “application/octet-stream”;
    Response.AddHeader(“Pragma”, “public”);
    Response.AddHeader(“Cache-Control”, “max-age=10”);
    Response.AddHeader(“Content-Disposition”, “attachment; filename=test.csv”);

    Any ideas? Thanks.

  48. Thanks Duncan, your method works for my site which uses SSL that annoys the crap out of me. For both IE and FF> :) Whee now I can work better!

  49. Thank you so much. Your fix was the only one that worked for me. The “if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘MSIE’)) session_cache_limiter(“public”);” that is.

  50. Guys, thanks everyone for the ideas. I tried various combinations. Finally, the below code worked and saved me from more agony. Many thanks to Harry School & Duncan. post-check=0 and pre-check=0 did the trick.

    header(“Content-Disposition: attachment; filename=filenamehere.csv;”);
    header(“Content-Type: text/csv”);

    if(strpos($_SERVER[‘HTTP_USER_AGENT’], ‘MSIE’))
    header(‘Cache-Control: must-revalidate, post-check=0, pre-check=0’);
    header(‘Pragma: public’);
    header(‘Pragma: no-cache’);

  51. Hi people, I might be shouting at the wrong crowd…

    But I can’t get IE’s authentication to “carry over” to Excel’s web query, could any of you coders help please?


  52. Sorry, I should have mentioned that it worked before but it doesn’t now…
    It works on my manager’s laptop with his parasite-browser (sorry I don’t know what else to call it – I believe this “browser” uses the IE-engine but runs its own interface)…

    & yes my default browser is IE (& I thought that would help…)

    Thanks in advance for anyone who’s giving this some thought.
    & since I don’t know much about coding, I thought this “might be part of the puzzle”.


  53. Using IIS and IE8. Had same problem where the csv would not open. It worked for years but when I added code to make my site IE10 compliant (in my case I told the browser to act like it was IE8, way too much code to change to make it truly IE10). Anyway the problem occured and the post from “Harry School” on (Fri 1 Dec 2006 at 4:39 am) worked for me.

    My asp file has this in it and it works fine now.

    Response.ContentType = “application/octet-stream”
    Response.AddHeader “content-disposition”,”attachment; filename=” & sfile & “.CSV”
    Response.CacheControl = “Cache-Control: must-revalidate, post-check=0, pre-check=0”

    I was missing the last line.

    Thanks so much!

Leave a Reply

Your email address will not be published. Required fields are marked *