我们在SQL数据库中存储了一些文件。在一个ASP.NET MVC3表单上,我们展示了两个链接:
查看此文件 | 下载此文件
这些链接指向对应的操作方法。下载正常工作--点击链接会在浏览器中弹出保存对话框。然而,显示会导致重复的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"
我尝试将自定义的content-disposition标头更改为用双引号包含文件名,但它仍向浏览器发送了2个标头。 我还尝试在添加自定义标头之前删除Content-Disposition标头,但似乎attachment标头是在返回FileContentResult之后添加的。
这段代码以前可以工作。 我昨天进行了测试,发现它不再在Chrome或Firefox中工作。 这可能是由于浏览器更新导致的。 IE8和Safari仍然可以正确打开文件。
更新
再次感谢Darin,你是正确的。 我们实际上使用了这种方法,因为我们参考了你回答过的另一个问题。
关于如何最终解决我们的问题,我们为显示文件链接设置了自定义路由:
context.MapRoute(null,
"path/to/display-file-attachment/{fileId}/{fileName}",
new
{
area = "AreaName",
controller = "ControllerName",
action = "DisplayFile",
}
);
页面上的超链接通过路由参数将文件名传递给操作方法,因此它已经成为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);
}
}