【发布时间】:2011-08-15 03:51:58
【问题描述】:
我在将存储在数据库中的文件发送回 ASP.NET MVC 中的用户时遇到问题。我想要的是一个列出两个链接的视图,一个用于查看文件并让发送到浏览器的 mimetype 确定应如何处理,另一个用于强制下载。
如果我选择查看一个名为SomeRandomFile.bak 的文件并且浏览器没有关联的程序来打开这种类型的文件,那么默认为下载行为我没有问题。但是,如果我选择查看一个名为 SomeRandomFile.pdf 或 SomeRandomFile.jpg 的文件,我希望文件能够简单地打开。但我也想保留一个下载链接,这样无论文件类型如何,我都可以强制下载提示。这有意义吗?
我已经尝试过FileStreamResult,它适用于大多数文件,它的构造函数默认不接受文件名,因此未知文件会根据 URL 分配一个文件名(它不知道要给出的扩展名基于内容类型)。如果我通过指定文件名来强制使用它,我将失去浏览器直接打开文件的能力,并且会收到下载提示。有没有其他人遇到过这种情况?
这些是我迄今为止尝试过的示例。
//Gives me a download prompt.
return File(document.Data, document.ContentType, document.Name);
//Opens if it is a known extension type, downloads otherwise (download has bogus name and missing extension)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType);
//Gives me a download prompt (lose the ability to open by default if known type)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType) {FileDownloadName = document.Name};
有什么建议吗?
更新:
这个问题似乎引起了很多人的共鸣,所以我想我会发布一个更新。 Oskar 添加的关于国际字符的以下已接受答案的警告是完全有效的,由于使用了 ContentDisposition 类,我已经打了几次。我已经更新了我的实现来解决这个问题。虽然下面的代码来自我最近在 ASP.NET Core(完整框架)应用程序中解决此问题,但由于我使用的是 System.Net.Http.Headers.ContentDispositionHeaderValue 类,因此它也应该在旧 MVC 应用程序中进行最小的更改。
using System.Net.Http.Headers;
public IActionResult Download()
{
Document document = ... //Obtain document from database context
//"attachment" means always prompt the user to download
//"inline" means let the browser try and handle it
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = document.FileName
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
return File(document.Data, document.ContentType);
}
// an entity class for the document in my database
public class Document
{
public string FileName { get; set; }
public string ContentType { get; set; }
public byte[] Data { get; set; }
//Other properties left out for brevity
}
【问题讨论】:
标签: c# asp.net-mvc asp.net-mvc-3 download http-headers