如何使用 MVC3 FileContentResult 避免重複的內容處置標頭?
我們有一些文件儲存在 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); }