嗨我不会在没有触摸磁盘驱动器的情况下自己处理上传流。 所以,我的自然选择是多方模块。
我采用了一般示例,并根据页面https://npmjs.org/package/multiparty的说明将form.parse更改为非回调请求。在这种情况下,不会触及磁盘。
我的代码如下所示:
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
关闭事件没有生成,所以我不知道什么时候读取套接字的结束。 如果我改变了行:
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
)
然后一切都很好,并且调用close事件。但是文件存储在磁盘上。控制台看起来像这样:
Part
Part
Received 65536, 337353
Received 131072, 337353
Received 196608, 337353
Received 262144, 337353
Received 327680, 337353
Received 337353, 337353
close received
知道什么是错的吗?
答案 0 :(得分:5)
在这种情况下,由于您没有将数据传输到文件,因此仅当所有数据都从close
对象传出时才会发出req
,导致req
在内部发出它的finish
事件,触发多方close
事件。
实际上,如果您需要close
事件,请始终将数据从部件中拉出,无论是黑洞还是有意义的位置(文件或临时保持流)。这也意味着使用close
事件继续控制流程可能非常棘手。
如果你不想对数据做任何事情,你可以像这样黑洞:
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
转出。
节点流仅在其缓冲区之间一次传输几个块。因此,小文件能够将整个缓冲区从req
传输到part
,而无需填充part
的内部缓冲区。较大的文件将填充part
的缓冲区,但仍有req
中的数据,需要读取part
以获取req
缓冲区中剩余的数据
这一事实也使得将close
事件用于控制流的任何事情都很棘手。例如,part
仍然可以处理,但close
将再次发送,因为close
不依赖part
完成,而是依赖于req
是空的。混乱!
答案 1 :(得分:1)
我认为您至少需要在某处读取任何收到的部分才能完成请求处理,并触发关闭事件:
form.on('part', function(part) {
part.pipe(fs.createWriteStream('/dev/null'));
});
如果没有这个,我想这就像你的请求仍在等待处理。 (请注意,除了“&gt; / dev / null”之外,还有更优雅,更少脚本的方式,但它只是作为示例;)