最佳答案
我遇到了一个问题,将存储在数据库中的文件发送回ASP中的用户。净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(全框架)应用程序,它应该与旧MVC应用程序中的最小变化一起工作,因为我使用的是System.Net.Http.Headers.ContentDispositionHeaderValue
类
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
}