为什么Internet Explorer无法使用NodeJS和Express下载PDF?

edh*_*ose 2 pdf ssl internet-explorer node.js

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

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

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

我通过NodeJS和Express(v3,beta2)/ Connect框架(它是为该文件提供服务的Connect Static中间件)提供文件.我也通过SSL提供服务,但关闭它似乎不是救命.

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

编辑 - 包括更多细节:

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

这是为文件提供服务的应用程序路径.静态服务组件确实有效,因此问题似乎在IE如何检索文件或如何将表达式提供给IE中.

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

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

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

在Fiddler,我看到以下内容. IE对PDF的多个请求. 2失败,1成功

前两个请求失败,而第三个请求成功传递PDF.

如果还有其他我能提供的,请告诉我.

edh*_*ose 5

所以,我想出了问题(或者至少是解决方案或4).

我花了一段时间和大量的研究,测试案例和各种各样,但我最终到了那里.

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

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

Range: bytes=a-b, c-d
Run Code Online (Sandbox Code Playgroud)

其中ab是范围而cd是范围,它看起来不连续.

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

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

[
   { start: a, end: b },
   { start: c, end: d}
]
Run Code Online (Sandbox Code Playgroud)

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

我相信Adobe 9会继续等待更多数据,这会导致我看到的悬挂.

解决方案

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

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