Internet Explorer Cannot Download https://something


Earlier today, I was asked to troubleshoot a secure site where file downloads were always failing. Having seen this problem many times often over the years, I immediately suspected that the web developer wasn’t aware that

if a user tries to download* a file over a HTTPS connection, any response headers that prevent caching will cause the file download process to fail.

* Note that this applies to “downloaded” files that open in programs other than IE. It does not apply to resources that render inside IE’s HTML rendering engine, like images/script/css/etc.

When Internet Explorer encounters a HTTPS download that will not be cached, the download is aborted with the following dialog box:

Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found.

The Fiddler web debugger allows you to easily check to see whether a download contains headers that prevent caching.

Cache-preventing headers include:

  • A Cache-Control header with the tokens no-cache, no-store
  • A Vary header that specifies almost anything 
  • A Pragma header that specifies exactly no-cache

Without changing the site’s code, you can easily confirm that the problem is caused by cache-prevention headers using Fiddler’s Filters tab:

Fiddler Filter UI: Remove Cache-Control Header

Fiddler allowed me to determine that today’s instance was caused by cache-preventing headers. After the web developer updates these headers to allow local caching (e.g. Cache-Control: private, max-age=15) the file download process will work correctly.

-Eric

PS: In the unlikely event that the user has checked the Do not save encrypted pages to disk option inside Tools / Internet Options > Advanced, this error dialog may be shown for any file downloads from secure sites, regardless of caching headers. I recommend that folks avoid enabling this option, and use the Delete Browser History on Exit feature instead.

Update Oct. 2010: I’ve conducted some further investigation of this issue, and found that (surprisingly) you CAN specify Cache-Control: no-store, no-cache and the download will work, but if you specify these directives in the opposite order, it will fail. Additionally, if you include a Pragma: no-cache header, the secure response will not be cached regardless of other headers. As a comment notes below, the behavior is slightly different for direct navigation (e.g. URL in the address bar) vs. a hyperlink navigation (e.g. user clicks on a link).

Update Feb. 2011: I’ve modified the file download logic for IE9. IE9 should be able to successfully download a file regardless of HTTPS or Cache-Control headers unless you have the “Do not save encrypted pages to disk” option set.

Comments (45)

  1. Billy Hoffman says:

    Can you clarify "downloaded files" a bit more? Does only apply to files with "Content-Disposition" response headers? Or is it simply any response with a Content-Type which IE does not handle natively?

  2. EricLaw says:

    @Billy: "this applies to “downloaded” files that open in programs other than IE" means "any response with a Content-Type which IE does not handle natively."

  3. Adam Barth says:

    This behavior seems kind of silly.  Is there a particular threat we’re protecting against?  Is copy/paste blocked too?  Blocking these downloads seems like it will just discourage people from using HTTPS.

  4. Brianary says:

    If a secure (SSL) web app builds content to the filesystem and points the browser at those files for download, it also must modify the IIS settings for that file, or it will fail for IE‽

    > "this applies to “downloaded” files that open in programs other than IE" means "any response with a Content-Type which IE does not handle natively."

    Content-Type based on the header, or content type detected by sampling the data?

  5. EricLaw says:

    > "This behavior seems kind of silly."

    🙂 I’ve used a variety of words to describe it, most of which are a bit harsher than "silly."

    I should have noted that this behavior has existed since (at least) IE6.  It’s something that major customers (especially banks) had asked for, without really understanding what it would mean for the user-experience.

    Obviously (considering the confusing UI) this wasn’t a scenario where a major investment was made.

    > "it also must modify the IIS settings for that file, or it will fail for IE‽"

    No, unless IIS configuration had already been modified to send a "no-cache" header. By default, IIS wouldn’t send this header, and hence this problem would not be encountered.

    > "Content-Type based on the header, or content type detected by sampling the data?"

    The distinction is irrelevant in this case.

  6. Huns Warst says:

    > It’s something that major customers (especially banks) had asked for,[…]

    Wait, so this is not a bug but a feature? I still don’t get what the security gain could be. AFAIK, https traffic shouldn’t be cached anyway. And on top of that, if that’s a ‘security feature’ why this misleading error message?!

    Apropos banks requesting security features, what about "X-Force-TLS"?

  7. EricLaw says:

    << AFAIK, https traffic shouldn’t be cached anyway.>>

    That’s an incorrect assumption.

    << what about "X-Force-TLS"? >>

    A number of folks are interested in the Strict Transport Security spec.

  8. Huns Warst says:

    « That’s an incorrect assumption. »

    Maybe, for when some evil villain is able to read your cache (the one on the disk) all is lost anyway.

    The equivalent of "Do not save encrypted pages to disk" is in Firefox the the about:config entry "browser.cache.disk_cache_ssl" which is set to "false" by default. So – unlike IE – Firefox isn’t caching content coming through HTTPS par default. I guess Mozilla had their reasons for deciding on this default behaviour, particularly as it means a sacrifice of performance on HTTPS pages.

    BTW/OT: I wish I will also find my life’s calling where I would be so dedicated that I would reply to blog post comments on Sundays. 🙂

  9. EricLaw says:

    "Firefox isn’t caching content coming through HTTPS par default"

    Last time I looked, in current Firefox versions, if a Cache-Control: public header is present, Firefox will cache the HTTPS-delivered content.

  10. Will H. says:

    The setting makes complete sense on shared machines. If someone decides to access their inbox on a public computer with auto-login, other people shouldn’t be able to dig up what they were looking at over SSL. Perhaps I’m too paranoid but I always make sure that setting is checked. Thanks for the heads-up about Firefox, Eric.

  11. EricLaw says:

    @WillH: Generally speaking, it’s never safe to browse private sites on an untrusted PC, because the PC may contain keyloggers or other spy software.

    Rather than tweaking the setting (which doesn’t really work like you hope it does), you should use the "Delete Browser History" command or IE8’s InPrivate Browsing feature.

  12. Adam Barth says:

    @WillH: The problem with disabling caching for all HTTPS traffic is that it makes HTTPS slower and more expensive for web site operators.  That means fewer of them will deploy HTTPS and everyone’s security suffers to mitigate this marginal threat.

    If you don’t want something cached, send a cache header with that instruction!

  13. Ryan B. says:

    I tried the idea of changing the values for Cache-Control, Expire…etc! But didn’t work, but when I tried changing the value of header ‘Pragma’ from ‘Pragma: no-cache’ to ‘Pragma: ‘, it works!

    Works in FF, IE, Safari, and Google Chrome.

    Thanks for the idea… God speed everyone!

  14. EricLaw [MSFT] says:

    @Ryan: You shouldn’t be sending a Pragma header at all. But yes, if you send a Pragma that forbids caching, you’ll see behavior as described in this post.

  15. Don Pratt says:

    I’m running into this on my site but we’re using straight HTTP, not HTTPS.  We have caching disabled (Cache-control: no-cache) for our download area due to a customer request.  Strangely, the problem only happens if I type in the URL to the file directly: http://www.aesc-inc.com/download/SPC/2010/SPC2010Install.exe”>http://www.aesc-inc.com/download/SPC/2010/SPC2010Install.exe .  If I go to our download page (http://www.aesc-inc.com/download/SPC/ ) and click the link, it works just fine.

    Any ideas?

  16. Simon J says:

    Like Don, I get this error using HTTP and not HTTPS and only if the user follows a link within an email or types the URL in IE directly. Strangely it only happens to users within our corporate network. External visitors can access the files fine either via links or by entering the address directly into the browser. Enabling caching is not an option as we then get an alternative error "myfile.xls is locked for editing by 'me' Open 'Read-Only', or click 'Notify' to open read-only…"

    Is there any resolution to this?

  17. schin says:

    I developed a activex. and signed it, and make cab file,  and  also signed it. It worked fine when download from http://something in WinXP and windows7 (IE7)client.

    but when download from https://something in WinXP and windows7  (IE7)client. it doesn't work. (can't download anything)

    in Win XP, I checked  [Do not save encrypted pages to disk] option, so download activex OK from https://something.

    but windows7 still can't work.

    Is there any resolution to this?

    Any advice please.

  18. EricLaw [MSFT] says:

    @DonPratt, @SimonJ, @Schin: Please send me (via email) the exact headers on the response. You can capture these via the Fiddler Web Debugger (www.fiddler2.com); for HTTPS sites, you'll need to enable HTTPS decryption in the Fiddler options.

  19. schin says:

    I solved my problem now.

    The cause is we used tomcat as our  web server. the tomcat add Cache-Control header  when the server site is https.

    thank you very  much.

  20. Jose says:

    Hi Eric; right now I'm having this issue at the QA server, but there's a little problem, I wasn't  using any kind of cache control.

    In my localhost it works just fine, but at QA displays that error, so i added the control cache that you used as example and it keeps going fine in my local

    and keeps sending the error message at the QA server, could you please give me some advice?

    This is the code (well, the part that is making me get hairless); I forgot, is Classic ASP and the QA server is not HTTPS

    Response.Buffer = TRUE

    Response.Clear()

    Response.ContentType = "application/vnd.ms-excel"

    Response.AddHeader "Cache-Control: private, max-age=15","attachment; filename=Reporte_Detallado.xls"

    Thanks in advance

  21. EricLaw [MSFT] says:

    @Jose: And if that's literally your code, the line AddHeader is wrong. You're trying to add two headers with just one line, and that won't work. I think you mean to say:

    Response.AddHeader "Cache-Control", "private, max-age=15"

    Response.AddHeader "Content-Disposition", "attachment; filename=Reporte_Detallado.xls"

  22. Drew says:

    I am facing the same problem. Mine is JSP with tomcat with https… It works fine in fire fox it breaks in IE.. any work around for this…

  23. EricLaw [MSFT] says:

    @Drew: The article itself talks about workarounds, which leads me to believe that you're having some other problem entirely. If you email me a network trace (www.fiddler2.com), I'm happy to have a look at it.

  24. Iain says:

    Great post, though I'm still having problems. I've tried amending my .net code, as suggested above, by adding:

        Response.AddHeader "Cache-Control", "private, max-age=15"

    but that hasn't solved it. After that change, I've used Fiddler to delete the Cache-Control header as directed, but I was still getting an Expires: -1 so also had to delete the pragma header (by entering "pragma; cache-control" in the Fiddler 'Delete response header' textbox). This then allowed the download of an Excel file from a page served over https

    My question is, what else do I need to do in my code ? Perhaps this :

           HttpContext.Current.Response.Cache().SetExpires(DateTime.Now.AddMinutes(15))

    Thanks in advance.

    Iain.

  25. EricLaw [MSFT] says:

    @Iain: Pragma: no-cache will prevent caching. If your page is sending that, you need to reconfigure it not to. If you don't know how to suppress that header, you'll need to ask in an ASP.NET forum.

  26. Iain says:

    Thanks Eric. I've got it working now. In case it helps others, here's my code:

           HttpContext.Current.Response.Clear()

           HttpContext.Current.Response.ClearHeaders()

           HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", fileName))

           HttpContext.Current.Response.AddHeader("Cache-Control", "private, max-age=15")

           HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"

           HttpContext.Current.Response.Cache().SetExpires(DateTime.Now.AddMinutes(15))

    I imagine it's the ClearHeaders() statement that has removed the pragma header.

  27. Zach says:

    Thanks a lot Eric for the article. It saved me from a tough debugging session.

    Your tip on the header "Cache-Control: no-store, no-cache" was a great hint. I got my file working over SSL now. Thank you once again, have a good day!

  28. Jan says:

    Thanks, you just saved my sanity. Beer is on me!

  29. VJ says:

    Thanks. This worked for JSP , Tomcat, HTTPS. Set the Header follows on HttpServletResponse:
    response.setHeader(CACHE_CONTROL,  "private, max-age=15");
    response.setHeader(PRAGMA,"");

  30. Aaron Margosis says:

    Coming very late to this conversation, but to those who say that no HTTPS content should ever be written to disk, what if you have a paystub site that gives you your paystub as a PDF?  How do you get that PDF to open in your PDF reader if you don't have it on disk?  What if you want to print something?  The print spooler operates on files.

    As Eric says, if someone can access your Temporary Internet Files folder, they have lots of other ways to control your user account; e.g., capture the HTML or other data after it has been downloaded by your browser and decrypted.  HTTPS provides point to point encryption, but at the endpoints it's in the clear.

  31. Roger Crawfis says:

    IE changes the extension on almost all file downloads, forcing me to save as change the extension and then open. This happens with Groupon when I try to print a voucher for instance. Furthermore, when I download an executbale (.exe) it changes the extension. It is like there is a remapping of the period to an underscore for anything but .htm or .html.

    [EricLaw]: This is a configuration problem somewhere on your machine. Please contact me using the link at the top-right to  let us investigate.

  32. Brian Wells says:

    Very cool – thanks for the help.  

    Was able to get it working via:

          string attachment = "attachment; filename=" + rptName + ".xls" + "";    

           HttpContext.Current.Response.Clear();

           HttpContext.Current.Response.ClearHeaders();

           HttpContext.Current.Response.AddHeader("content-disposition", attachment);

           HttpContext.Current.Response.AddHeader("Cache-Control", "private, max-age=1");

           HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";

           HttpContext.Current.Response.Charset = "";

           HttpContext.Current.Response.Buffer = true;

           HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddMinutes(1));

  33. Eddie says:

    We had the exact same issue. In our case the problem was caused by McAfee HBSS/IDS

  34. Jon Hargett says:

    This is for the one other person in the world that will run in to this:

    I have some old code that uses the Tabular Data Control (msdn.microsoft.com/…/ms531356%28v=vs.85%29.aspx). I ran in to this issue when I had a script that generates a CSV file. In the headers I had a Pragma: no-cache. This file was then being consumed by the TDC over https. In IE8, it would not display the content over https, but would over http. In IE9 it worked fine. I spent some time looking for the bug and found the problem with the header by trial and error. Then after finding it, I did a search for Pragma: no cache over https and found this site. Thanks for helping me to see what was causing the error.

  35. EricLaw [MSFT] says:

    @Jon: Yup, that's exactly the same culprit. There's some more discussion of this in this post: blogs.msdn.com/…/downloads-and-flash-fail-when-do-not-save-encrypted-pages-to-disk-is-set.aspx

  36. Tito says:

    When I download any file over HTTPS, the resulting file is corrupt. Using the same code over HTTP is fine.

    I've tried various combinations of:

    Response.AddHeader "Cache-Control", "private, max-age=15"

    Response.AddHeader "Pragma", "no-cache"

    Response.AddHeader "cache-control", "no-store, must-revalidate, private"

    Response.AddHeader "Cache-Control", "no-store, no-cache"

    at different code locations. Do these lines need added at a certain location, e.g. before adding other headers?

  37. EricLaw says:

    @Tito: Can you explain what specifically is "corrupt" in the cases you're referring to? What browser are you using, and what are the final set of headers?

  38. Ian Boyd says:

    i've seen the same issue when trying to "view source" of an xml file. If my web-server tells the browser *"do not cache"*, then Internet Explorer does as it's told, and saves **no** copy of the file.

    The logic of the (original) situation seems "reasoanble" when you explain it that way. How can an external program (like Excel or Notepad) open a file off the hard-drive, when Internet Explorer has been told not to save a copy.

    One reason for specifying "no-cache" is so that the browser will always get a *"fresh"* copy of the server. Another reason can be that the information is somewhat sensitive, and we'd rather you didn't keep a copy on the hard-drive if at all possible.

  39. Charli says:

    Having much the same problem:  Using IE9-x64 on Windows 7 Ultimate.  NOT using "do not save encrypted pages".  HAVE set BypassSSLNoCacheCheck=1.  STILL cannot save downloads from banks to disk using IE9.  Can do this with Mozilla.  What's going on?

  40. Pentaho & "Cache-Control: no-cache" headers says:

    We've experienced this problem with IE8 and Pentaho.  Unable to download reports generated by the system using IE8 but could using IE9 and other browsers when using SSL.  In the end we fronted it with an Apache server doing SSL termination, and configured Apache with "mod_headers" to remove the offending headers.

    This didn't work on it's own, we also had to disable the "Do not store encrypted pages to disk" setting.

  41. Devin says:

    I've changed Cache-Control: and Pragma: and downloads in IE8 through SSL now work but only if you type the URL into the address bar. If you click on the link in an email it still gives the error. Fiddler shows that in both cases the headers are identical. What gives?

    EricLaw: And what, exactly, are the headers in question?

  42. Tomas Hesse says:

    Thank you for a very interesting and hopefully useful blog.

    I have the opposite problem. Getting IE (10) to stop caching my page. I have an  .aspx that draws (bars using System.Drawing and the bitmap i then saved as a physical but temporary .png  and rendered whit an htmlImage scr=…png. There is a dropdown (time) causing postbacks but the images are never regenerated due to caching. Chrome and FireFox works fine but IE just don't quit

  43. EricLaw says:

    @Tomas: What are the exact headers on the HTTP response? One *very rare* issue I've seen with ASP.NET partial-page updates is that images with unchanged URLs can be reused out of Trident's per-page image cache, so request doesn't even go to the network stack where cache headers would be evaluated. But this is very rarely the issue, the most common problem is failure to set proper headers on the response.

  44. Devin says:

    @EricLaw: Thanks for the response. In both cases the headers are identical and as follows:

    HTTP/1.1 200 OK
    Date: Thu, 24 Oct 2013 02:46:03 GMT
    Server: Apache/2.2.16 (Debian)
    Vary: Host
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache
    Pragma: private
    Content-Disposition: attachment; filename="19062351.doc"
    Content-Length: 4905
    Connection: close
    Content-Type: text/rtf

    Again, pasting or typing the URL into the address bar works but clicking on it in an email does not. Interestingly, sometimes the first time you paste it into the address bar you get the same error but clicking go or hitting enter a second time works. This is IE8 on WinXP. Prior to setting Cache-Control: no-store, no-cache and Pragma: private the links were never working in IE8, now they are working just not when clicked on in an email. I've also tried the other variations for Cache-Control: listed on this page and the behavior stays the same.

    Thanks Eric I really appreciate your feedback, I can't find any solution for this online, everything just mentions the Cache-Control: and Pragma: headers that I think I already have set correctly.

    [EricLaw] Remove the meaningless Pragma header. Remove the Vary header. Change the Cache-Control header to be Cache-Control: private, max-age=10.

    Devin

  45. Devin says:

    Thank you so much Eric, for the response. The Pragma: and Vary: headers were being set if I didn't specify them so I looked into explicitly removing them. You were right, that and changing Cache-Control to 'private, max-age=10' did the trick. Its working now with these headers:

    HTTP/1.1 200 OK

    Date: Sat, 26 Oct 2013 20:02:32 GMT

    Server: Apache/2.2.16 (Debian)

    Expires: Thu, 19 Nov 1981 08:52:00 GMT

    Cache-Control: private, max-age=10

    Content-Disposition: attachment; filename="19062351.doc"

    Content-Length: 4905

    Connection: close

    Content-Type: text/rtf

    For those who are interested, I'm using PHP and this is the code I used to get it working:

    // check for IE only headers

    if (isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)) {

    header('Cache-Control:  private, max-age=10');

    header_remove('Pragma');

    header_remove('Vary');

    }

    Thanks again Eric, I really appreciate your help on this.