为什么multipart不会产生closures事件

嗨,我不会处理上传stream自己没有接触磁盘驱动器。 所以,我的自然select是多方面的模块。

我采取了一般的例子,并根据https://npmjs.org/package/multiparty页面的说明我把form.parse改为非callback请求。 在这种情况下,磁盘将不会被触摸。

我的代码如下所示:

multiparty = require("multiparty") http = require("http") util = require("util") # show a file upload form http.createServer((req, res) -> if req.url is "/upload" and req.method is "POST" form = new multiparty.Form() form.on 'error', (err) -> console.log "Error received #{err}" form.on 'aborted', -> console.log "Aborted" form.on 'part', (part) -> console.log "Part" form.on 'close', (part) -> console.log "close received" res.writeHead 200, "content-type": "text/plain" res.end "received upload:\n\n" form.on 'progress', (bytesReceived, bytesExpected) -> console.log "Received #{bytesReceived}, #{bytesExpected}" form.parse req else res.writeHead 200, "content-type": "text/html" res.end "<form action=\"/upload\" enctype=\"multipart/form-data\" method=\"post\">" + "<input type=\"text\" name=\"title\"><br>" + "<input type=\"file\" name=\"upload\" multiple=\"multiple\"><br>" + "<input type=\"submit\" value=\"Upload\">" + "</form>" ).listen 8080 

控制台输出如下所示:

 Part Part Received 64983, 337353 Received 130519, 337353 Aborted Error received Error: Request aborted 

closures事件不会生成,所以我不知道什么时候读取socket的结束。 如果我改变这一行:

 form.parse req 

至:

 form.parse req, (err, fields, files) -> res.writeHead 200, "content-type": "text/plain" res.write "received upload:\n\n" res.end util.inspect( fields: fields files: files ) 

然后一切都很好,closures事件被称为。 但该文件存储在磁盘上。 控制台看起来像这样:

 Part Part Received 65536, 337353 Received 131072, 337353 Received 196608, 337353 Received 262144, 337353 Received 327680, 337353 Received 337353, 337353 close received 

任何想法有什么不对?

在这种情况下,由于不是将数据传输到文件,所以只有当所有数据已经​​从req对象pipe道输出时才发出close ,从而导致req在内部发出它的finish事件,从而触发多方close事件。

实际上,如果您需要close事件,请始终将数据从部件中拉出,无论是黑洞还是有意义的位置(文件或临时存储stream)。 这也意味着使用close事件来持续控制stream量可能非常棘手。

如果你不想对数据做任何事情,你可以像这样黑洞:

 form.on("part", function(part) { out = new stream.Writable(); // require("stream") to get this native class out._write = function (chunk, encoding, done) { done(); // Don't do anything with the data }; part.pipe(out); }); 

令人困惑的部分是,不访问该part代码将调用小文件的close事件,但不能在大文件上调用(我如何处理这个问题)。 这是因为close事件并不限于是否已经读取了该part的数据,而是所有的数据是否已经被传送出req

节点stream只能在缓冲区之间一次传输几个块。 因此,小文件能够将其整个缓冲区从req传输到part而不用填充part的内部缓冲区。 较大的文件将填充该part的缓冲区,但仍有数据遗留在req ,需要读取该part以获取req缓冲区中的数据。

这个事实也使得使用close事件来处理控制stream的任何事情都非常棘手。 在例子中,一个part仍然可以被处理,但是close会被发送,因为close不依赖于part完成,而是req是空的。 混乱!

我认为你至less需要读取任何接收到的部分,以完成请求处理,并触发closures事件:

 form.on('part', function(part) { part.pipe(fs.createWriteStream('/dev/null')); }); 

没有这个,我想这就像你的请求还在等待处理。 (请注意,比起“/ dev / null”这个东西更优雅,脚本比较less,但这只是一个例子;)