使用 parse: false in Hapi multipart/form-data 时,Stream 似乎只有 1 个块

问题描述

我有一个接收流的端点:

    server.route({
    method: 'PUT',path: `${FILES_PREFIX}`,handler: Handlers.createFile,options: {
        description: 'Create file.',tags: ['api','file'],payload: {
            timeout: false,maxBytes: 10 * GB,output: 'stream',multipart: true,parse: false,allow: 'multipart/form-data',}
    }
});

如果我设置 parse: true 我会按预期收到我的缓冲区,并且可以在 payload.data 上读取它。但是,由于我的文件太大,我需要自己解析它(否则我得到: RangeError [ERR_OUT_OF_RANGE]: The value of "length" is out of range. It must be >= 0 &&

所以我尝试的解决方案是设置 parse: false 并自己解析流。但是,当我查看我的有效负载时,我看到我有 readableBuffer() 返回一个缓冲区列表……但缓冲区列表只有 1 个 64kb 的元素。第一个元素 .next 值为空。我只是在那里询问我的其余数据在哪里。

我还尝试查看 request.raw.req,因为解析是错误的,所以无论如何我都不应该将所有数据都放在缓冲区中......但它在 request.raw.req 和 request.payload 中的信息基本上相同。我在 request.raw.req().readableBuffer()

上也有 64kb 的 readableBuffer

解决方法

默认解析器绝对不适合这种大小的传输,因为它将所有传入数据缓冲到内存中。

您走在正确的轨道上,但您没有按预期使用流 API。 readableBuffer() 方法只返回当前缓冲的内容。要接收更多数据并正确使用它,您需要使用适当的流 API:

  1. 使用 'data'end' 事件。
  2. stream.read()'readable' 事件一起使用。
  3. 只需 stream.pipe() 到另一个流。

对于所有这些,您都需要注册并适当处理 'error' 事件。

最现代的方法是使用 Stream.pipeline() 助手。

最后,流可能不是最佳解决方案。 Hapi 还支持 'file' 输出模式,它将输入直接流式传输到磁盘上的文件。