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
之类的东西来封装“当网络为它们准备好时我将提供字节”的想法。
File
将enablePartialContent
的第三个参数设置为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 中的身份验证 cookie 无效?
如何使 ASP.NET Core Web API 操作异步执行?