如何使用 MVC3 FileContentResult 避免重复的内容处置标头? [英] How to avoid duplicate content-disposition headers with MVC3 FileContentResult?

查看:37
本文介绍了如何使用 MVC3 FileContentResult 避免重复的内容处置标头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一些文件存储在 sql 数据库中.在 ASP.NET MVC3 表单上,我们显示 2 个链接:

We have some files stored in sql database. On an ASP.NET MVC3 form, we display 2 links:

查看此文件 |下载此文件

View this file | Download this file

这些链接指向这些相应的操作方法.下载按预期工作——单击链接会强制浏览器中出现保存对话框.但是,显示会导致向浏览器发送重复的 Content-Disposition 标头,从而导致 Chrome 出现错误,以及 Firefox 中的空白页面.

These links go to these corresponding action methods. The download works as expected -- clicking a link forces a save dialog in the browser. However, the display is causing duplicate Content-Disposition headers to be sent to the browser, resulting in an error on Chrome, and an empty page in Firefox.

[ActionName("display-file")]
public virtual ActionResult DisplayFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        Response.AddHeader("Content-Disposition", 
            string.Format("inline; filename={0}", file.Name));
        return File(file.Content, file.MimeType, file.Name);
    }
}

[ActionName("download-file")]
public virtual ActionResult DownloadFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        return File(file.Content, file.MimeType, file.Name);
    }
}

以下是发送到浏览器用于显示操作的 2 个标头:

Here are the 2 headers sent to the browser for the display action:

Content-Disposition: inline; filename=name-of-my-file.pdf
Content-Disposition: attachment; filename="name-of-my-file.pdf"

我尝试更改自定义内容处置标头以将文件名括在双引号中,但它仍然向浏览器发送了 2 个标头.我还尝试在添加自定义标头之前删除 Content-Disposition 标头,但似乎在返回 FileContentResult 后添加了附件标头.

I tried changing my custom content-disposition header to wrap the file name in double quotes, but it still sent 2 headers to the browser. I also tried removing the Content-Disposition header before adding the custom one, but it appears the attachment header is being added after the FileContentResult is returned.

此代码曾经有效.我昨天刚刚进行了一个测试,发现它在 Chrome 或 Firefox 中不再有效.这可能是由于浏览器中的更新.IE8 和 Safari 仍然可以正确打开文件.

This code used to work. I ran a test just yesterday and noticed it is no longer working in Chrome or Firefox. This could be due to updates in the browsers. IE8 and Safari still open the file correctly.

更新

再次感谢 Darin,你是对的.我们实际上使用这种方法是因为您回答的另一个问题.

Thanks again Darin, you are correct. We actually used this approach because of another question you answered.

关于我们最终如何解决这个问题的更多信息,我们有一个用于显示文件链接的自定义路由:

A little more info about how this was ultimately solved on our end, we have a custom route for the display file link:

context.MapRoute(null,
    "path/to/display-file-attachment/{fileId}/{fileName}",
    new
    {
        area = "AreaName",
        controller = "ControllerName",
        action = "DisplayFile",
    }
);

页面上的超链接通过路由参数将文件名传递给action方法,所以它已经是URL的一部分了.因此,当用户决定下载文件(通过单击浏览器 PDF 查看器中的保存图标)时,我们不需要添加自定义内容处理标题以使文件名与系统匹配.所以我们就用了这个:

The hyperlink on the page passes the file name to the action method through the route parameter, so it is already part of the URL. Thus, we did not need to add a custom content-disposition header in order to make the file name match the system's when a user decided to download it (by clicking save icon in browser PDF viewer). So we just used this:

[ActionName("display-file")]
public virtual ActionResult DisplayFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        // no custom content-disposition header, and no 3rd fileName argument
        return File(file.Content, file.MimeType);
    }
}

推荐答案

当你使用重载 File(byte[] contents, string mimeType, string fileName) 一个 Content-Disposition 标头会通过 attachment 自动添加到响应中,因此您无需再次添加.对于 inline,您可以使用以下重载 File(byte[] contents, string mimeType) 并手动添加 Content-Disposition 标头:

When you use the overload File(byte[] contents, string mimeType, string fileName) a Content-Disposition header is automatically added to the response with attachment, so you don't need to add it a second time. For inline you could use the following overload File(byte[] contents, string mimeType) and manually add the Content-Disposition header:

[ActionName("display-file")]
public virtual ActionResult DisplayFile(Guid fileId)
{
    var file = _repos.GetFileInfo(fileId);
    var cd = new ContentDisposition
    {
        Inline = true,
        FileName = file.Name
    };
    Response.AddHeader("Content-Disposition", cd.ToString()); 
    return File(file.Content, file.MimeType);
}

[ActionName("download-file")]
public virtual ActionResult DownloadFile(Guid fileId)
{
    var file = _repos.GetFileInfo(fileId);
    return File(file.Content, file.MimeType, file.Name);
}

这篇关于如何使用 MVC3 FileContentResult 避免重复的内容处置标头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆