使用Asp MVC 4.0 FileResult的Internet Explorer错误

时间:2012-04-03 15:19:11

标签: asp.net-mvc-4 asp.net-mvc

我有以下代码,部署在https Asp站点上,使用MVC 4.0构建:

public FileResult ANotSoWorkingFunction(string filePath, string fileName)
{
 pathToFile = string.Format("~/{0}/{1}", pathToFile, fileName);
 return File(new FileStream(pathToFile, FileMode.Open), "application/pdf", fileName);
}

这对于Chrome,Firefox和IE9都有效(正如你们许多人可能已经猜到的那样)。但它会抛出一个:

---------------------------
Windows Internet Explorer
---------------------------
Internet Explorer cannot download someFileName from a_site.com.


Internet Explorer was not able to open this Internet site.  The requested site is either unavailable or cannot be found.  Please try again later.
---------------------------
OK   
---------------------------

在IE6,7,8上

我非常感谢任何关于这个的想法或线索,因为我已经花了很多时间来玩html标题。

编辑:

以下是IE7的标题:

HTTP/1.1 200 OK
Cache-Control: private, no-cache="Set-Cookie"
Content-Type: application/pdf
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 4.0
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH=; expires=Mon, 11-Oct-1999 21:00:00 GMT; path=/; HttpOnly
X-Powered-By: ASP.NET
Date: Wed, 04 Apr 2012 08:43:50 GMT
Content-Length: 233324

这是来自IE9的那些:

HTTP/1.1 200 OK
Cache-Control: private, no-cache="Set-Cookie"
Content-Type: application/pdf
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 4.0
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH=; expires=Mon, 11-Oct-1999 21:00:00 GMT; path=/; HttpOnly
X-Powered-By: ASP.NET
Date: Wed, 04 Apr 2012 08:42:14 GMT
Content-Length: 233324

谢谢,

3 个答案:

答案 0 :(得分:8)

我想我也遇到了你的问题。

我也在运行IIS 7.5并通过HTTPS请求上的操作下载PDF。由于我尚未分离的原因,IIS 7.5似乎将no-cache="Set-Cookie"附加到我的Cache-Control响应标头,无论我在响应上设置缓存设置。这导致the fairly well documented no-cache issue on IE6, IE7, and IE8

为了解决这个问题,我在FileContentResult周围做了一个小包装,它清除了标题,称为父标题,然后将Cacheability设置为' Private'。这方面支持IIS 7.5坚持在标题中添加no-cache="Set-Cookie",并在我测试的所有浏览器中正确下载文件。如果你想模仿我所做的,首先,这里是我的FileContentResult包装器。

public class PdfContentResult : FileContentResult {

    public PdfContentResult(byte[] data) : base(data, "application/pdf") { }

    public PdfContentResult(byte[] data, string fileName) : this(data) {
        if (fileName == null) {
            throw new ArgumentNullException("fileName");
        }

        this.FileDownloadName = fileName;
    }

    public override void ExecuteResult(ControllerContext context) {
        context.HttpContext.Response.ClearHeaders();

        base.ExecuteResult(context);

        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.Private);
    }
}

然后我向我的ControllerExtensions添加了一个扩展方法,以便找到它:

public static class ControllerExtensions {

    public static PdfContentResult Pdf(this Controller controller, byte[] fileContents, string fileName) {
        return new PdfContentResult(fileContents, fileName);
    }

}

最后,在Action中,我做了相同的事情:

public ActionResult MyGeneratedPdf() {
    byte[] myPdfContentInByteStream = GetPdfFromModel();
    return this.Pdf(myPdfContentInByteStream, "MyFile.pdf");
}

显然,如果您要下载各种数据类型,您可能不希望将解决方法与PDF紧密绑定。

答案 1 :(得分:1)

我们通过在流式传输文件之前更改缓存控制标头来解决此问题。

简化代码示例:

var browserInformation = Request.Browser;

//Set as private if current browser type is IE
Response.AppendHeader("cache-control", 
                    browserInformation.Browser == "IE" ? "private" : "no-cache");

return File(fileName, contentType, downloadFileName);

这有效(yay)..但是我不知道为什么我们必须以这种方式为特定网站这样做。我们有四个网站在同一个盒子上运行,所有这些网站都在SSL下,只有一个网站有这个标题问题。我比较了web.config文件并查看了IIS中的设置,但无法进一步说明为什么一个站点需要明确设置这些头文件。

如果有人有更多要添加上面(添加的clairty)那将是伟大的。

答案 2 :(得分:0)

在旧版本的IE中,如果用户尝试通过HTTPS连接下载文件,则任何阻止缓存的响应标头都将导致文件下载过程失败。以下是引起问题的最常见标题:

  • 使用值no-cache或no-store
  • 进行缓存控制
  • 随着任何价值而变化
  • 具有值no-cache的Pragma

您可以创建一个ActionFilterAttribute,它将为您清除缓存标头:

public class ClearCacheHeadersAttribute : FilterAttribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        return;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        HttpContext.Current.Response.Headers.Remove("Cache-Control");
        HttpContext.Current.Response.Headers.Remove("Vary");
        HttpContext.Current.Response.Headers.Remove("Pragma");

        //Set the cache headers any way you like keeping in mind which values can brake the download
    }
}

用它装饰你的动作:

[ClearCacheHeaders]
public FileResult ANotSoWorkingFunction(string filePath, string fileName)
{
    pathToFile = string.Format("~/{0}/{1}", pathToFile, fileName);
    return File(new FileStream(pathToFile, FileMode.Open), "application/pdf", fileName);
}