【问题标题】:Starting a file download before you finalize its contents在最终确定其内容之前开始文件下载
【发布时间】:2020-04-26 05:55:55
【问题描述】:

在我的 web 应用程序中,用户可以选择下载包含一些数据的文件,他们可以通过单击按钮来完成。对于少量数据,文件几乎立即开始下载,并显示在浏览器的下载区域中。哪个好。

对于大量数据,服务器可能需要大量时间来计算数据,甚至在我们开始下载之前。这是不好的。我想指出计算正在进行中。但是我不想在我的 UI 上放置“忙碌”指示器,因为该操作不会阻塞 UI - 用户应该能够在准备文件时做其他事情。

从我的角度来看,一个好的解决方案是在我完成计算之前开始下载过程。我们总是知道(或可以快速计算)文件的前几百个字节。有没有一种机制可以让服务器用这几个字节响应下载请求,从而开始下载并使文件显示在下载区域中,并在我完成计算后提供文件的其余部分?我知道下载看起来会停止,这不是问题。

我可以非常快速地估算出文件大小。我宁愿不必使用第三方包来实现这一点,除非它是一个非常简单的包。我们正在使用 Angular,但如果需要,我们很乐意编写原始 JS。

【问题讨论】:

  • 请提供有关您的服务器端代码、java、tomcat 的更多详细信息?还请提供有关下载如何为您工作的一些详细信息...您是否将文件存储在数据库中?
  • 我们的服务器是 C#,但我正在寻找一个通用的解决方案。该文件未存储在数据库中。我们需要根据 API 参数创建它。

标签: javascript http


【解决方案1】:

要表明链接指向客户端上的下载,最简单的方法是链接上的download 属性。该属性的存在告诉浏览器不要卸载当前选项卡或创建新选项卡;该属性的值是建议的文件名。

对于后端部分,设置正确的响应头后,只需将数据写入输出流即可。

【讨论】:

  • 实际上,最佳实践(如果您正在生成大量数据)是将数据管道到输出流,同时将背压一直传播到进程生成该数据 - 以避免生成比客户端下载的速度快得多,这将迫使您的服务器将多余的内存保留在内存中,直到可以接收。
【解决方案2】:

您要求通用解决方案

1) 首先,在您的 HTML/JS 中,您可以通过设置下载 target 到任何其他网页来防止 UI 被阻止,这样做的首选方法是设置目标到IFRAME

<!-- your link must target the iframe "downloader-iframe" -->
<a src="../your-file-generator-api/some-args?a=more-args" target="downloader-iframe">Download</a>
<!-- you don't need the file to be shown -->
<iframe id="downloader-iframe" style="display: none"></iframe>

2) 其次,在您的后端,您必须同时使用 Content-DispositionContent-Length(可选)标头,如果您错过了,请小心使用“长度”标头计算fileSize 它不会被下载。如果您不使用Content-Length,您将看不到“下载进度”。

3) 第三,在您的后端,您必须确保在响应中直接写入字节!这样你的浏览器和你的网络服务器就会知道下载正在“进行中”,

如何这 3 个步骤的构建将取决于您,您正在使用的框架和库,例如 Dojo 和 JQuery 具有出色的 IFRAME 操作实用程序,所有人都认为您可以通过以下方式进行编码你自己,这是一个 JQuery 示例:

Using jQuery and iFrame to Download a File

还有:

添加“忙碌”动画就可以了!您只需要确保它不会阻止您的 UI,如下所示:

【讨论】:

    猜你喜欢
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多