12

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

查看此文件 | 下载这个文件

这些链接转到这些相应的操作方法。下载按预期进行——单击链接会强制在浏览器中出现保存对话框。但是,显示会导致将重复的 Content-Disposition 标头发送到浏览器,从而导致 Chrome 出现错误,并导致 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 个标头:

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

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

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

更新

再次感谢达林,你是对的。由于您回答的另一个问题,我们实际上使用了这种方法。

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

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

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

[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);
    }
}
4

1 回答 1

29

当您使用重载时File(byte[] contents, string mimeType, string fileName)Content-Disposition标头会自动添加到响应中attachment,因此您无需再次添加它。因为inline您可以使用以下重载File(byte[] contents, string mimeType)并手动添加Content-Disposition标题:

[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);
}
于 2011-12-23T13:48:32.740 回答