将文件返回到ASP.NET MVC中的视图/下载

19 浏览
0 Comments

将文件返回到ASP.NET MVC中的视图/下载

我在ASP.NET MVC中遇到一个问题,即将存储在数据库中的文件发送回用户。我想要一个视图,列表中有两个链接,一个用于查看文件并让MIME类型确定应如何处理,另一个则强制下载。

如果我选择查看名为SomeRandomFile.bak的文件,并且浏览器没有关联的程序来打开此类型的文件,则默认为下载行为没有问题。然而,如果我选择查看名为SomeRandomFile.pdfSomeRandomFile.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
}

:这是一段包含着加粗文本“123”的HTML代码。

admin 更改状态以发布 2023年5月22日
0
0 Comments

由于"document"变量没有类型提示,我对接受的答案遇到了问题: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);
}

0
0 Comments

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

0