2011-12-23 70 views
10

我们有一些存储在sql数据库中的文件。在一个ASP.NET MVC3的形式,我们会显示2个链接:如何避免与MVC3 FileContentResult重复的内容处置标题?

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

这些链接到这些相应的操作方法。下载按预期工作 - 单击链接会在浏览器中强制保存对话框。但是,显示导致重复的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仍然正确打开文件。

更新

再次感谢达林,你是正确的。由于another question you answered,我们实际上使用了这种方法。

有关如何这是最终解决了我们这边出了一点信息,我们为显示文件链接的自定义路线:

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); 
    } 
} 
+0

Firefox和Chrome确实成为了它们的处理内容处置头的更为严格。 – 2011-12-23 13:59:15

+0

@JulianReschke,请您详细说明非ASCII字符?我们还没有在文件名中使用unicode字符进行测试。 – danludwig 2011-12-23 14:10:19

+0

对于C-D中的非ASCII文件名,在所有浏览器中“工作”,服务器当前需要进行User-Agent嗅探。请参阅http://greenbytes.de/tech/tc2231/和http://greenbytes.de/tech/webdav/rfc6266.html。我有我的怀疑,ASP.net得到这个权利,但我很想找出其他方式。 – 2011-12-24 09:17:40

回答

24

当您使用过载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); 
} 
+0

你打败了我,我即将发布类似的答案。省略第三个fileName参数。但是,我们不需要添加内容处置。简单地'返回文件(file.Content,file.MimeType);'工作,因为文件名是从一个自定义路由派生。 – danludwig 2011-12-23 13:50:55

+0

那么,希望这个框架能够处理非ASCII字符的问题...... – 2011-12-23 13:58:37

+0

@JulianReschke,什么非ASCII字符?该框架对他们无所作为。随你便。如果你正在谈论文件名中的非ASCII字符,那么是的,那是可怕的PITA。但这不是你希望框架能够帮助你的东西。这只是由不同浏览器实现的不同而已。总之,这是不应该使用的:-) – 2011-12-23 14:13:02