10

我正在编写一个小型 node.js 应用程序,它从 HTML 表单接收多部分 POST 并将传入数据通过管道传输到 Amazon S3。强大的模块提供多部分解析,将每个部分公开为一个节点Streamknox模块将PUT 处理到 s3。

var form = new formidable.IncomingForm()
 ,  s3   = knox.createClient(conf);

form.onPart = function(part) {
    var put = s3.putStream(part, filename, headers, handleResponse);
    put.on('progress', handleProgress);
};

form.parse(req);

我正在通过socket.io向浏览器客户端报告上传进度,但很难让这些数字反映节点到 s3 上传的真实进度。

当浏览器到节点的上传几乎是瞬间发生时,就像节点进程在本地网络上运行时一样,进度指示器立即达到 100%。如果文件很大,即 300MB,进度指示器会缓慢上升,但仍然比我们的上行带宽允许的要快。在达到 100% 进度后,客户端然后挂起,大概是在等待 s3 上传完成。

我知道在内部putStream使用 Node 的stream.pipe方法,但我不明白它是如何工作的细节。我的假设是节点尽可能快地吞噬传入的数据,并将其放入内存中。如果写入流可以足够快地获取数据,则很少有数据一次保留在内存中,因为它可以被写入和丢弃。但是,如果写入流很慢,就像这里一样,我们可能必须将所有传入的数据保留在内存中,直到可以写入为止。由于我们正在侦听data读取流上的事件以发出进度,因此我们最终报告上传速度比实际速度快。

我对这个问题的理解是否接近标记?我该如何修复它?我需要对write, drainand感到沮丧和肮脏pause吗?

4

1 回答 1

8

您的问题是stream.pause未在 上实现part,这是多部分表单解析器输出的非常简单的读取流。

Knox 指示 s3 请求在部件发出 "data" 时发出 "progress" 事件。然而,由于part流忽略了暂停,进度事件的发送速度与表单数据的上传和解析速度一样快。

然而,强大的form确实知道如何处理pauseresume(它代理对它正在解析的请求的调用)。

这样的事情应该可以解决您的问题:

form.onPart = function(part) {

    // once pause is implemented, the part will be able to throttle the speed
    // of the incoming request
    part.pause = function() {
      form.pause();
    };

    // resume is the counterpart to pause, and will fire after the `put` emits
    // "drain", letting us know that it's ok to start emitting "data" again
    part.resume = function() {
      form.resume();
    };

    var put = s3.putStream(part, filename, headers, handleResponse);
    put.on('progress', handleProgress);
};
于 2012-11-13T00:58:01.623 回答