Asp.net-Mvc-3

如何使用 MVC3 FileContentResult 避免重複的內容處置標頭?

  • October 10, 2016

我們有一些文件儲存在 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);
   }
}

當您使用重載時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);
}

引用自:https://stackoverflow.com/questions/8616691