2

我有一个使用 NodeJS 构建的网站,它需要提供一些 PDF(以及其他文件)。

由于我无法确定的原因,Internet Explorer 8 第一次无法在 Acrobat Viewer 中完全下载 PDF(有时之后多次)。直接保存文件就可以了,但这并不理想。Chrome 工作正常,虽然我没有测试过其他浏览器。

没有错误消息,除了状态栏停止更新并显示:( 来源:twimg.com已下载(16.33 MB 中的 2.97 MB):

我通过 NodeJS 和 Express (v3, beta2) / Connect 框架提供文件(它是提供文件的 Connect Static 中间件。)我也通过 SSL 提供它,但关闭它似乎没有帮助。

任何想法将不胜感激!谢谢

编辑- 包括更多细节:

首先 - 我已经从 Express v2 升级到 v3 以尝试解决这个问题 - 没有这样的运气。

这是提供文件的应用程序路由。静态服务组件确实有效,因此问题似乎在于 IE 如何检索文件或 express 如何将它们提供给 IE。

app.get('/store/*', ensureAuthenticated, express.static(__dirname + '/../uploads'));

function ensureAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {    
        return next();
    }
} else {
    res.redirect('/login');
}

至于错误 - 我在 IE 中看不到 404 错误或任何内容。它只是挂着一个空白屏幕,上面的图片显示了左下角状态栏中的下载量。Adobe 最终(约 5 分钟后)失败并发出警告:“此文件已损坏,无法修复”。我知道文件没有损坏,因为偶尔 IE加载它(请参阅下面的 Fiddler 请求)。

在 Fiddler 中,我看到以下内容。 来自 IE 的多个 PDF 请求。 2失败,1成功

前两个请求失败,而第三个请求成功交付了 PDF。

如果还有什么我可以提供的,请告诉我。

4

1 回答 1

5

所以,我发现了问题(或者至少是一个或 4 个解决方案)。

我花了一段时间和大量的研究、测试用例和各种各样的东西,但我最终到达了那里。

当 IE8(也可能还有其他浏览器,但我没有进行广泛测试)使用 Adob​​e 9(未经 Adob​​e X 或任何其他版本验证)插件请求 PDF 时,有时它会将整个文件作为一个获取。这是我看到的成功,对应于上面 Fiddler 屏幕截图中的请求 22。如果文件很小,它似乎会抓取整个文件,但在这种情况下,我使用 16MB PDF 进行测试。

在其他情况下,Adobe 将发送此表单的范围标头:

Range: bytes=a-b, c-d

其中 ab 是一个范围,而 cd 是一个范围,它看起来是不连续的。

我对 Range 标头的了解并不广泛,所以我不确定这是否有效。我所做的研究表明不是。

无论如何,在 Connect 的 static.js 中,它使用 lib/util.js 中称为 parseRange 的范围解析方法。此方法以下列形式返回一个范围数组:

[
   { start: a, end: b },
   { start: c, end: d}
]

在 static.js 中,它调用此方法并将值分配给range,然后使用range[0]计算范围,从而忽略值cdab之间的范围是从文件中读取并发送到请求的唯一数据。

我相信 Adob​​e 9 然后继续等待更多数据,这导致了我看到的挂起。

解决方案

  • 最简单的解决方案是删除 static.js 中的标头“Accept-Ranges”
  • 我实施的一个更复杂(不一定正确)的解决方案是采用ac的最小值以及bd的最大值来创建一个新范围并在范围检查代码中返回它。这个要点显示了我所做的:https ://gist.github.com/2930131
  • 我相信第三种(可能的)解决方案是监视客户端何时继续等待数据并对连接执行某些操作(关闭它,发送更多数据 - 我不确定!)。我真的不知道这将如何工作,但我会尝试将它推荐给可能的人。

第二个解决方案适用于我的用例。我希望如果你偶然发现它对你也有用!

于 2012-06-14T13:19:37.213 回答