Asp.Net Core:如何使浏览器在发送之前显示文件正在下载

Posted

技术标签:

【中文标题】Asp.Net Core:如何使浏览器在发送之前显示文件正在下载【英文标题】:Asp.Net Core: how to make the browser show file as being downloaded before it's sent 【发布时间】:2019-03-22 20:55:58 【问题描述】:

我有以下正在生成文件的操作:

public async Task<IActionResult> GetFile()

    //some long running action to actually generate the content 
    //(e.g. getting data from DB for reporting)
    await Task.Delay(10000); 

    return File(new byte[], "application/octet-stream");

问题在于,当用户点击该链接时,在点击某个操作和浏览器显示文件正在下载之间存在很长的延迟。

我真正想要的是 ASP.Net 发送带有文件名的标题(这样浏览器会向用户显示文件已开始下载)并在生成文件内容时延迟发送正文。可以这样做吗?

我尝试了以下方法:

public async Task GetFile()

    HttpResponse response = this.HttpContext.Response;
    response.ContentType = "application/octet-stream";
    response.Headers["Content-Disposition"] = "inline; filename=\"Report.txt\"";

    //without writing the first 8 bytes 
    //Chrome doesn't display the file as being downloaded 
    //(or ASP.Net doesn't actually send the headers). 
    //The problem is, I don't know the first 8 bytes of the file :)            
    await response.WriteAsync(string.Concat(Enumerable.Repeat("1", 8)));

    await response.Body.FlushAsync();

    await Task.Delay(10000);
    await response.WriteAsync("1234567890");

上面的代码可以正常工作,如果我不必 response.WriteAsync 发送标头的前 8 个字节,我会很高兴的。

还有其他方法可以克服吗?

【问题讨论】:

我可以发誓有某种类型可以让您返回某种类型的FileContentResult,您实际上承诺提供对Stream 之类的对象的访问,它可以从中提取字节因为它已准备好通过电线发送它们,但我现在找不到它。我想如果我只是梦想它,您可以自己实现一些Stream 之类的东西来封装“当网络为它们准备好时我将提供字节”的想法。 FileenablePartialContent 的第三个参数设置为true,看看它是否有效。 有 FileStreamResult (github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/…),但是根据源代码它会读取流直到结束并退出(即如果流中没有数据,它将立即退出,而无需等待流填充数据) @Damien_The_Unbeliever 我想你可能指的是PushStreamContent Stephen Cleary 写了一篇可能有帮助的帖子:Streaming Zip on ASP.NET Core。显然,这是关于编写 .zip,但这些概念应该适用于您的用例。 【参考方案1】:

实际上,有问题的代码可以正常工作。 问题是,Chrome doesn't show file as being downloaded until 8 bytes are sent

但是,如果您想编写类似的东西,请考虑阅读 Stephen Cleary's post 一些有用的抽象。

【讨论】:

以上是关于Asp.Net Core:如何使浏览器在发送之前显示文件正在下载的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET Core 中发送邮件

如何在 ASP.NET Core 5 中向特定用户发送内容

如何使 ASP.NET Core 中的身份验证 cookie 无效?

如何使 ASP.NET Core Web API 操作异步执行?

如何使 Asp.NET Core MVC 应用程序在授权重定向上使用外部 url?

如何在 C# 中将数据发送到 ASP.NET Core MVC 控制器?