返回文件以在 ASP.NET MVC 中查看/下载 [英] Returning a file to View/Download in ASP.NET MVC

查看:26
本文介绍了返回文件以在 ASP.NET MVC 中查看/下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm encountering a problem sending files stored in a database back to the user in ASP.NET MVC. What I want is a view listing two links, one to view the file and let the mimetype sent to the browser determine how it should be handled, and the other to force a download.

如果我选择查看一个名为 SomeRandomFile.bak 的文件并且浏览器没有关联的程序来打开这种类型的文件,那么我没有问题,它默认为下载行为.但是,如果我选择查看名为 SomeRandomFile.pdfSomeRandomFile.jpg 的文件,我希望该文件可以简单地打开.但我也想保留一个下载链接,以便我可以强制下载提示,而不管文件类型如何.这有意义吗?

If I choose to view a file called SomeRandomFile.bak and the browser doesn't have an associated program to open files of this type, then I have no problem with it defaulting to the download behavior. However, if I choose to view a file called SomeRandomFile.pdf or SomeRandomFile.jpg I want the file to simply open. But I also want to keep a download link off to the side so that I can force a download prompt regardless of the file type. Does this make sense?

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

I have tried FileStreamResult and it works for most files, its constructor doesn't accept a filename by default, so unknown files are assigned a file name based on the URL (which does not know the extension to give based on content type). If I force the file name by specifying it, I lose the ability for the browser to open the file directly and I get a download prompt. Has anyone else encountered this?

这些是我迄今为止尝试过的示例.

These are the examples of what I've tried so far.

//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 类.

UPDATE: This questions seems to strike a chord with a lot of people, so I thought I'd post an update. The warning on the accepted answer below that was added by Oskar regarding international characters is completely valid, and I've hit it a few times due to using the ContentDisposition class. I've since updated my implementation to fix this. While the code below is from my most recent incarnation of this problem in an ASP.NET Core (Full Framework) app, it should work with minimal changes in an older MVC application as well since I'm using the System.Net.Http.Headers.ContentDispositionHeaderValue class.

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
}

推荐答案

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 类正确地说明了这一点.- 奥斯卡 2016-02-25

NOTE: This example code above fails to properly account for international characters in the filename. See RFC6266 for the relevant standardization. I believe recent versions of ASP.Net MVC's File() method and the ContentDispositionHeaderValue class properly accounts for this. - Oskar 2016-02-25

这篇关于返回文件以在 ASP.NET MVC 中查看/下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆