为什么multipart不会产生近距离事件

Lum*_*n75 1 http node.js coffeescript express

嗨,我不会自己处理上传流而不接触磁盘驱动器.所以,我的自然选择是多方模块.

我拿了一般的例子,根据页面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 
Run Code Online (Sandbox Code Playgroud)

控制台输出如下所示:

Part
Part
Received 64983, 337353
Received 130519, 337353
Aborted
Error received Error: Request aborted
Run Code Online (Sandbox Code Playgroud)

close事件没有生成,所以我不知道什么时候读取套接字的结束.如果我换行:

form.parse req
Run Code Online (Sandbox Code Playgroud)

至:

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
  )
Run Code Online (Sandbox Code Playgroud)

然后一切都很好,关闭事件被调用.但是文件存储在磁盘上.控制台看起来像这样:

Part
Part
Received 65536, 337353
Received 131072, 337353
Received 196608, 337353
Received 262144, 337353
Received 327680, 337353
Received 337353, 337353
close received
Run Code Online (Sandbox Code Playgroud)

知道什么是错的吗?

Nuc*_*eon 5

在这种情况下,由于您没有将数据传递给文件,close因此仅在所有数据都已从req对象传出时req发出,从而导致内部发出它的finish事件,从而触发multiparty 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);
});
Run Code Online (Sandbox Code Playgroud)

令人困惑的部分是,不访问的代码part将调用close小文件的事件,但不会在大文件上调用(我如何遇到这个问题).这样做的原因是close事件不受你是否已经从中读取数据的约束,part而是所有数据是否已经从中传输出来req.

节点流仅在其缓冲区之间一次传输几个块.因此,小文件能够将其整个缓冲区从中传输reqpart不填充part内部缓冲区.较大的文件将填充缓冲区part但仍有剩余数据req,需要读取part以获取req缓冲区中剩余的数据.

这一事实也使得将close事件用于控制流程的任何事情都很棘手.在示例中,a part仍然可以处理,但是close将再次发送,因为close它不依赖于part完成,而是依赖于req空.混乱!