IE6-8 unable to download file from HTTPS site

后端 未结 2 985
滥情空心
滥情空心 2021-02-14 19:06

I have an MVC .Net application that has actions that return report files, usually .xslx:

byte[] data = GetReport();
return File(data, 
    \"applica         


        
相关标签:
2条回答
  • 2021-02-14 19:49

    I was having a similar approach in that I had a BaseController class

    [OutputCache(Duration=0)]
    public class BaseController : Controller
    {
        //snip snip: some utility stuff and shared endpoints among all my controllers
    }
    

    That caused the above mentioned problems in IE8. Applying the [IENoCacheAttribute] as shown above didn't work however. The problem is that the instruction filterContext.HttpContext.Response.ClearHeaders() removes all of my headers including eventual Content-Disposition headers etc... causing the file download to not happen correctly.

    My approach was therefore to overwrite the default OutputCacheAttribute.cs in such a way that in case of IE it didn't apply any kind of caching headers, especially the problematic no-cache ones.

    public class EnhancedOutputCacheAttribute : OutputCacheAttribute
    {
    
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
    
            if (!IsFileResultAndOldIE(filterContext))
                base.OnActionExecuted(filterContext);
            else
            {
                //try the best to avoid any kind of caching
                filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.Private);
                filterContext.HttpContext.Response.Cache.SetMaxAge(new TimeSpan(0));
                filterContext.HttpContext.Response.Cache.SetExpires(DateTime.Now.AddMinutes(-5D));
            }
        }
    
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!IsFileResultAndOldIE(filterContext))
                base.OnActionExecuting(filterContext);
        }
    
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            if (!IsFileResultAndOldIE(filterContext))
                base.OnResultExecuted(filterContext);
        }
    
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            if (!IsFileResultAndOldIE(filterContext))
                base.OnResultExecuting(filterContext);
        }
    
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterContext"></param>
        /// <returns><c>true</c> for FileResults and if the browser is < IE9</returns>
        private bool IsFileResultAndOldIE(dynamic filterContext)
        {
            return filterContext.Result is FileResult &&
                   filterContext.HttpContext.Request.IsSecureConnection &&
                   string.Equals(filterContext.HttpContext.Request.Browser.Browser, "IE", StringComparison.OrdinalIgnoreCase) &&
                   filterContext.HttpContext.Request.Browser.MajorVersion < 9;
        }
    
    }
    

    Here's the corresponding gist: https://gist.github.com/4633225

    0 讨论(0)
  • 2021-02-14 19:57

    I've come up with a workaround, but it's a definite hack - this is a new cache attribute to replace the built-in [OutputCache] one:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public sealed class IENoCacheAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsSecureConnection &&
                string.Equals(filterContext.HttpContext.Request.Browser.Browser, "IE", StringComparison.OrdinalIgnoreCase) &&
                filterContext.HttpContext.Request.Browser.MajorVersion < 9)
            {
                filterContext.HttpContext.Response.ClearHeaders();
                filterContext.HttpContext.Response.AddHeader("cache-control", "no-store, no-cache, must-revalidate");
            }
            else
            {
                filterContext.HttpContext.Response.Cache.SetNoStore();
                filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            }
    
            base.OnResultExecuting(filterContext);
        }
    }
    

    It's a workaround at best though - what I really want is to extend the existing [OutputCache] and Response.Cache structures so that they have the desired output suitable for legacy IEs.

    0 讨论(0)
提交回复
热议问题