从node.js报告上传进度

我正在编写一个小型的node.js应用程序,它从HTML表单接收多部分POST,并将传入的数据pipe理到Amazon S3。 强大的模块提供了多部分parsing ,将每个部分暴露为一个节点Stream 。 Knox模块将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上传的真实进度。

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

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

我对这个问题的理解是否接近标准? 我该如何去解决它? 我是否需要记下来, write下来, drainpause

你的问题是stream.pause没有在part上实现 ,这是多部分表单parsing器输出的一个非常简单的读取stream。

当部件发出“数据”时,Knox指示s3请求发出“进度”事件 。 但是由于partstream忽略了暂停,所以进度事件的发送速度与表单数据上传和parsing一样快。

但是,这个强大的form确实知道如何pauseresume (它代表了它正在parsing的请求的调用)。

像这样的东西应该可以解决你的问题:

 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); };