【问题标题】:Java Servlets: File download breaks when user navigates away from pageJava Servlets:当用户离开页面时文件下载中断
【发布时间】:2011-01-05 06:17:04
【问题描述】:

我有一个 servlet,它允许用户从网页下载(可能很大)zip 文件。如果用户点击一个链接来下载一个 zip 文件,则在 servlet 中执行类似于以下的代码:

response.setContentType("application/zip");
response.setHeader("Content-disposition", "attachment; filename=foo.zip");
response.setHeader("Pragma", "");
response.setHeader("Cache-Control", "no-store");

ZipOutputStream out = new ZipOutputStream(response.getOutputStream());
// write entries to the zip file...
...
out.close()

但是,如果用户在下载开始之后和完成之前(在 Firefox 3.5.7 中)刷新或离开页面,下载将失败。弹出如下错误:

C:\blah\foo.zip.part 不能 保存,因为源文件可以 不被阅读。

稍后再试,或联系服务器 管理员。

关于如何确保在这种情况下继续下载有什么想法吗?

更新:启动下载的链接是一个普通的链接。有趣的是,IE 上的行为是不同的。点击网站上其他地方的链接(从当前加载的屏幕)似乎没有加载(浏览器状态栏显示“等待https://mysite/clicked_linky.do...”),直到下载完成。在地址栏中键入不同的 URL 或使用快捷方式/收藏夹链接会离开页面,但下载会按预期继续。只有 Firefox 似乎显示了我上面描述的确切行为,尽管 IE 阻止不是最佳的。

【问题讨论】:

    标签: java http servlets download


    【解决方案1】:

    这实际上不应该发生。下载计为 单独 请求,该请求应该在调用后独立于父页面在后台运行。您究竟是如何触发下载请求的?通过普通链接或(错误地)触发 ajaxical 请求以运行下载的链接?

    无论如何,您至少显然希望能够恢复下载。在这种情况下,您需要在下载中相应地至少发送Accept-RangesETagLast-Modified 响应标头。然后,客户端可以通过发送 If-RangeRange 请求头来请求恢复下载,分别带有文件标识符和指定的字节范围,您可以将其与 RandomAccessFile 结合使用以发送剩余的字节。您可以在this article 中找到更多信息和 servlet 示例。

    这就是理论。在您的特定情况下,当您动态压缩文件时,这有点棘手。您需要先将 zip 文件写入服务器本地磁盘文件系统的临时文件夹,然后从中流式传输,最后在下载成功完成后删除文件 only(即out.close()没有抛出IOException)。您可以借助请求参数或路径信息或会话中的密钥来识别关联的 zip 文件。

    更新:根据您的更新:老实说,我不知道也从未经历过,但至少我可以告诉you're not the only one who suffered from this problem。至少,如前所述实现恢复功能可能是解决这个特定问题的方法,因为 Firefox 会自动恢复下载,而不会因为不完整的部分而急于求成。

    更新 2:在阅读您的更新和浏览器行为后稍加思考后,看起来在触发实际请求和响应标头到达之间存在相当大的时间间隔。我不知道您如何加载文件的确切细节,但 看起来 收集 ZIP 文件需要时间(也许您事先从网络文件系统或数据库加载它们?) 并且您仅在收集所有 ZIP 文件之后 设置/发送响应标头。尝试设置标题并在执行昂贵的任务之前执行output.flush() before。这样,浏览器将尽快获取标头,并且知道它可能期望什么。

    【讨论】:

    • 我同意,如果客户端将浏览器带到另一个页面或刷新,独立下载 servlet 请求不应该搞砸。我已经用 Java 实现了一个下载 servlet,它没有遇到任何这些问题。
    【解决方案2】:

    我怀疑这是使用 servlet 的人工制品 - 可能是重新分配线程的结果。当然,用 PHP 编写的类似设置我没有这样的问题(每个请求都由一个(有效的)新进程处理。

    HTH

    C.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多