首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在ASP.NET MVC中返回要查看/下载的文件

在ASP.NET MVC中返回要查看/下载的文件
EN

Stack Overflow用户
提问于 2011-04-29 08:38:50
回答 9查看 427.5K关注 0票数 325

我在将存储在数据库中的文件发送回ASP.NET MVC中的用户时遇到问题。我想要的是一个列出两个链接的视图,一个用来查看文件并让发送给浏览器的mimetype决定如何处理它,另一个用来强制下载。

如果我选择查看一个名为SomeRandomFile.bak的文件,而浏览器没有相关的程序来打开这种类型的文件,那么我对它默认的下载行为没有任何问题。但是,如果我选择查看一个名为SomeRandomFile.pdfSomeRandomFile.jpg的文件,我希望该文件只是打开。但我也希望在边上保留一个下载链接,这样无论文件类型如何,我都可以强制显示下载提示。这有意义吗?

我尝试过FileStreamResult,它适用于大多数文件,默认情况下它的构造函数不接受文件名,所以未知文件会根据URL分配一个文件名(它不知道根据内容类型给出的扩展名)。如果我通过指定文件名来强制它,我将失去浏览器直接打开该文件的能力,并且我会得到一个下载提示。还有没有人遇到过这种情况?

这些是我到目前为止已经尝试过的例子。

代码语言:javascript
复制
//Gives me a download prompt.
return File(document.Data, document.ContentType, document.Name);

代码语言:javascript
复制
//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);

代码语言:javascript
复制
//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类,我已经点击了几次。我已经更新了我的实现来修复这个问题。虽然下面的代码来自我在MVC (完整框架)应用程序中这个问题的最新化身,但由于我使用的是System.Net.Http.Headers.ContentDispositionHeaderValue类,因此它在较旧的ASP.NET应用程序中也应该只需最少的更改即可工作。

代码语言:javascript
复制
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
}
EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-04-29 17:13:26

代码语言:javascript
复制
public ActionResult Download()
{
    var document = ...
    var cd = new System.Net.Mime.ContentDisposition
    {
        // for example foo.bak
        FileName = document.FileName, 

        // always prompt the user for downloading, set to true if you want 
        // the browser to try to show the file inline
        Inline = false, 
    };
    Response.AppendHeader("Content-Disposition", cd.ToString());
    return File(document.Data, document.ContentType);
}

注意:上面的示例代码无法正确说明文件名中的国际字符。有关标准化的信息,请参阅RFC6266。我相信最近版本的ASP.Net MVC的File()方法和ContentDispositionHeaderValue类很好地解决了这个问题。- Oskar 2016-02-25

票数 448
EN

Stack Overflow用户

发布于 2015-06-17 21:42:40

由于在"document“变量中没有类型提示:var document = ...,所以我在可接受的答案上遇到了麻烦,所以我发布了对我有效的替代方案,以防其他人遇到问题。

代码语言:javascript
复制
public ActionResult DownloadFile()
{
    string filename = "File.pdf";
    string filepath = AppDomain.CurrentDomain.BaseDirectory + "/Path/To/File/" + filename;
    byte[] filedata = System.IO.File.ReadAllBytes(filepath);
    string contentType = MimeMapping.GetMimeMapping(filepath);

    var cd = new System.Net.Mime.ContentDisposition
    {
        FileName = filename,
        Inline = true,
    };

    Response.AppendHeader("Content-Disposition", cd.ToString());

    return File(filedata, contentType);
}
票数 136
EN

Stack Overflow用户

发布于 2016-04-22 00:58:34

Darin Dimitrov's answer是正确的。这只是一个补充:

如果您的响应已包含"Content-Disposition“标头,则Response.AppendHeader("Content-Disposition", cd.ToString());可能会导致浏览器无法呈现文件。在这种情况下,您可能需要使用:

代码语言:javascript
复制
Response.Headers.Add("Content-Disposition", cd.ToString());
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5826649

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档