为什么multipart不生成关闭事件 [英] Why multipart is not generating close events
问题描述
您好,我不会处理自己的上传流,而不触摸磁盘驱动器。
所以,我的自然选择是多方模块。
我采用一般的例子,根据 https://npmjs.org/package/multiparty 我将form.parse改为非回调请求。在这种情况下,磁盘将不会被触摸。
我的代码如下所示:
multiparty = require multiparty)
http = require(http)
util = require(util)
#显示文件上传表单
http.createServer req,res) - >
如果req.url是/ upload并且req.method是POST
form = new multiparty.Form()
form。 on'error',(err) - >
console.log收到错误#{err}
form.on'aborted', - >
console。 logAborted
form.on'part',(part) - >
console.logPart
form.on'close' (part) - >
console.logclose received
res.writeHead 200,
content-type:text / plain
res.endreceived上传:\\\
\\\
form.on'progress',(bytesReceived,bytesExpected) - >
console.logReceived#{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
控制台输出如下所示:
零件
零件
已接收64983,337353
已接收130519,337353
已中止
收到错误错误:请求已中止
不生成关闭事件,所以我不知道什么时候读取套接字。
如果我更改行:
form.parse req
到:
form.parse req, ,fields,files) - >
res.writeHead 200,
content-type:text / plain
res.writereceived upload:\\\
\\\
res.end util.inspect(
fields:fields
file:files
)
然后一切都很好,关闭事件被调用。但是文件存储在磁盘上。控制台如下所示:
零件
零件
收到65536,337353
收到131072 ,337353
收到196608,337353
收到262144,337353
收到327680,337353
收到337353,337353
收到
任何想法有什么问题?
解决方案这种情况下,由于你不是管道数据到文件,
close
只有当所有数据已经从req
对象,导致req
在内部发出完成
事件,触发多方close
事件。
在实践中,如果您需要
关闭
事件,无论是黑洞还是有意义的位置(文件或临时存储流)。这也意味着使用关闭
事件继续是非常棘手的控制流程。
如果你不想对数据做任何事情,你可以这样黑洞:
form.on(part,function(part){
out = new stream.Writable(); // require(stream)to get this native class
out._write = function(chunk,encoding,done){
done(); //不要对数据做任何事情
};
part.pipe );
});
令人困惑的部分是不能访问
c $ c>会为小文件调用
close
事件,但不能在大文件上调用(我遇到了这个问题)。这是因为close
事件不是绑定到你是否从部分
读取数据,而是是否所有数据都已传输出req
。
节点流每次只在其缓冲区之间传输几个块。因此,小文件能够将其整个缓冲区从
req
转移到部分
,而不填充部分
的内部缓冲区。较大的文件将填充部分
的缓冲区,但仍然有在req
中剩余的数据,部分
,以获取req
缓冲区中剩余的数据。
这个事实也使得使用
close
事件来处理关于控制流的任何事情都很棘手。例如,部分
仍然可以处理,但会发送close
,因为关闭
不依赖于部分
完成,而是依赖于req
为空。困惑!Hi I won't to handle upload stream by myself without touching a disk drive. So, the natural selection for me was multiparty module.
I took the general example and according the instruction from page https://npmjs.org/package/multiparty I changed form.parse to non callback request. In that case the disk won't be touched.
My code looks like this:
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
the console output looks like this:
Part Part Received 64983, 337353 Received 130519, 337353 Aborted Error received Error: Request aborted
The close event is not generated so I don't know when the end of reading the socket. If I change the line:
form.parse req
to:
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 )
Then everything is fine and the close event is called. But the file is stored on the disk. The console looks like this:
Part Part Received 65536, 337353 Received 131072, 337353 Received 196608, 337353 Received 262144, 337353 Received 327680, 337353 Received 337353, 337353 close received
Any idea what's wrong?
解决方案In this case, since you are not piping the data to a file,
close
is emitted only when all data has been piped out of thereq
object, causingreq
to internally emit it'sfinish
event, which triggers the multipartyclose
event.In practice, if you need the
close
event, always pull the data out of the part, whether it is to a blackhole or a meaningful location (file or temporary holding stream). This also means it can be very tricky to use theclose
event for continuing control flow.If you don't want to do anything with the data you can blackhole it like so:
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); });
The confusing part is that code which does not access the
part
will call theclose
event for small files, but not be called on large files (how I ran into this issue). The reason for that is that theclose
event isn't bound to whether you have read the data from thepart
but whether all data has been transferred out of thereq
.Node streams only transmit a few chunks at a time between their buffers. Thus, small files are able to transfer their entire buffer from
req
topart
without fillingpart
's internal buffer. Larger files will fill the buffer of thepart
but still have data left over in thereq
, requiring a read on thepart
to get the data remaining in thereq
buffer.This fact also makes it tricky to use the
close
event for anything regarding control flow. In example, apart
can still be processing, butclose
will be sent, again becauseclose
isn't dependent onpart
completion, but rather onreq
being empty. Confusing!这篇关于为什么multipart不生成关闭事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!