如何使用节点强大的 fileWriter StreamHandler [=10a 流管道?

how to assemble a stream pipleine with node-formidable fileWriteStreamHandler?

我正在尝试使用 node-formidable 方法 fileWriteStreamHandler 将文件上传到 S3。在上传到 S3 之前,我想创建一个文件哈希。这意味着实现一个流管道,它首先通过哈希传递数据,然后将该数据传递到 S3 上传。

在尝试实现管道时,我一直 运行 遇到问题。所以下面是一个简化的函数,或多或少代表了我想做的事情。

formHandler.js

const form = formidable({
  encoding: 'utf-8',
  keepExtensions: true,
  allowEmptyFiles: false,
  maxFiles, maxFileSize, maxTotalFileSize,
  maxFields, maxFieldsSize, minFileSize,
  multiples: true,
  fileWriteStreamHandler: streamUploadImage,
});

streamUploadImage.js

function streamUploadImage() {
  const firstStream = new PassThrough();
  const lastStream = new PassThrough();

  const hash = createHash('SHA2-256');
  hash.setEncoding('hex');
  const transform = new Transform({
    transform(chunk, encoding, cb) {
      hash.write(chunk);
      cb();
    },
    flush(cb) {
      hash.end();
      console.log('all done', hash.read());
      cb();
    }
  });

  firstStream.on('data', () => console.log('first'));
  lastStream.on('data', () => console.log('last'));

  return first.pipe(transform).pipe(last);
};

当使用上面的 streamUploadImage 时,只会调用 lastStreamfirstStream & transform 从未被调用。

这是为什么?管道是否未正确实施?强大的 fileWriteStreamHandler 不适用于管道吗?

使用formidable@3.2.1

更新: 请参阅下文以快速重现我的问题:

var server = http.createServer(function (req, res) {
  if (req.url == '/') {
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end(`
        <form action="/upload" enctype="multipart/form-data" method="post">
          <label>file name<input type="text" name="file_name" autofocus /></label><br />
          <label>single file<input type="file" name="file_single" /></label><br />
          <label>multiple files<input type="file" name="filearray_with_multiple[]" multiple /></label><br />
          <br />
          <button>Upload</button>
        </form>
      `);

      res.end();
  } else if (req.url === '/upload') {
    const form = formidable({
      encoding: 'utf-8',
      keepExtensions: true,
      allowEmptyFiles: false,
      multiples: true,
      fileWriteStreamHandler: streamUploadImage,
    });

    form.parse(req, (err, fields, files) => {
      if (err) throw err;

      console.log('parsed file upload');
      console.log({ fields, files });
      res.writeHead(201, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ err, fields, files}, null, 2))
    })
  }
});

function streamUploadImage() {
  const firstStream = new PassThrough();
  const lastStream = new PassThrough();

  const hash = createHash('SHA2-256');
  hash.setEncoding('hex');
  const transform = new Transform({
    transform(chunk, encoding, cb) {
      hash.write(chunk);
      cb();
    },
    flush(cb) {
      hash.end();
      console.log('all done', hash.read());
      cb();
    }
  });

  firstStream.on('data', () => console.log('first'));
  lastStream.on('data', () => console.log('last'));

  return firstStream.pipe(transform).pipe(lastStream);
};

server.listen(5000);

stream.pipe() return 允许链接的 目标 流。

您需要 return 来自 streamUploadImage() 的管道头部(在您的示例中为 firstStream),而不是尾部。

function streamUploadImage() {
  const firstStream = new PassThrough();
  const lastStream = new PassThrough();

  // *snip*

  // Wire up the pipeline
  firstStream.pipe(transform).pipe(lastStream);
  // Return the head of the pipeline
  return firstStream;
};