为什么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,但这只是一个例子;)