将文件返回到ASP.NET MVC中的查看/下载

Nic*_*cht 284 c# asp.net-mvc download http-headers asp.net-mvc-3

我在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);
Run Code Online (Sandbox Code Playgroud)

//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);
Run Code Online (Sandbox Code Playgroud)

//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};
Run Code Online (Sandbox Code Playgroud)

有什么建议?

Dar*_*rov 412

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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • var document = ...是什么类型的? (71认同)
  • 注意:如果你使用它并设置`Inline = true`,请确保不要使用`File()`的3-param重载,它将文件名作为第3个参数.它*将*在IE中工作,但Chrome会报告重复的标题并拒绝显示图像. (21认同)
  • 如果我没记错的话,只要文件名没有空格就可以不引用(我通过HttpUtility.UrlEncode()来实现这一点). (6认同)
  • @ user1103990,这是你的域模型. (6认同)
  • 使用MVC 5,不再需要content-disposition头,因为它已经是响应头的一部分.但是我只在FF中获得了一个下载对话框,在chrome和IE中没有对话框 (2认同)

ooX*_*1sh 113

由于没有对"文档"变量进行类型暗示,我在接受的答案上遇到了麻烦:var document = ...所以我发布了对我有用的东西,以防其他人遇到麻烦.

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 文档变量只是一个类(POCO),表示有关要返回的文档的信息.有人也接受了答案.它可能来自ORM,来自手动构建的SQL查询,来自文件系统(当您从中提取信息时)或其他一些数据存储.这与原始问题无关,你的文件字节/文件名/ mime类型来自哪里,所以它被排除在外,不会让代码变得混乱.感谢您仅使用文件系统提供示例. (3认同)
  • 在Edge中不起作用?不能让它工作 (2认同)

Leo*_*Leo 13

达林迪米特洛夫的回答是正确的.只是一个补充:

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

Response.Headers.Add("Content-Disposition", cd.ToString());
Run Code Online (Sandbox Code Playgroud)


Ash*_*ian 10

查看文件(例如txt):

return File("~/TextFileInRootDir.txt", MediaTypeNames.Text.Plain);
Run Code Online (Sandbox Code Playgroud)

下载文件(例如txt):

return File("~/TextFileInRootDir.txt", MediaTypeNames.Text.Plain, "TextFile.txt");
Run Code Online (Sandbox Code Playgroud)

注意:要下载文件,我们应该传递fileDownloadName参数


Ser*_*gan 5

我相信这个答案更清晰,(基于 /sf/answers/210536791/

    public ActionResult GetAttachment(long id)
    {
        FileAttachment attachment;
        using (var db = new TheContext())
        {
            attachment = db.FileAttachments.FirstOrDefault(x => x.Id == id);
        }

        return File(attachment.FileData, "application/force-download", Path.GetFileName(attachment.FileName));
    }
Run Code Online (Sandbox Code Playgroud)

  • 不推荐,出于清晰度和兼容性的考虑,Content-Disposition 是首选方法。http://stackoverflow.com/questions/10615797/utility-of-http-header-content-type-application-force-download-for-mobile (9认同)
  • 关于内容类型撒谎听起来是一个非常糟糕的主意。某些浏览器依赖于正确的内容类型在“保存或打开”对话框中为用户建议应用程序。 (2认同)