克隆节点文件对象以并行使用多个流 (Multer)

Cloning a Node File Object to use multiple streams in parallel (Multer)

是否可以克隆 Node.JS 文件对象?

我已经为 Multer 编写了一个自定义存储驱动程序,它在其构造函数中采用一组存储驱动程序并调用每个驱动程序的 ._handleFile。目标是将一个文件并行保存到多个目的地。

但是,磁盘驱动程序打开的文件流似乎会扰乱任何后续读取。在我的特殊情况下,我正在尝试保存到本地磁盘 + AWS-S3。

通过调试(setTimeouts等)发现:

所以我的假设是同一文件上的多个流会导致奇怪的问题。

多磁盘驱动程序执行以下操作:

  ...
  var outStream = fs.createWriteStream(finalPath)
  file.stream.pipe(outStream)

multer AWS S3 驱动程序执行此操作:

...
var upload = this.s3.upload(params)

我假设图书馆打开了一个流。

我不想先保存文件然后再手动创建两个流。我更愿意以某种方式复制文件对象并将它们发送给每个单独的 ._handleFile 方法。

 MultiStorage.prototype._handleFile = async function _handleFile (req, file, cb) {
 
   // I removed some code for this example
   ...
   const results = await Promise.all(drivers.map({ driver }, i) => {
     return new Promise((fulfill, reject) => {
       // file -> this I believe I need to duplicate
       driver._handleFile(req, file, (error, info) => {
         fulfill({ info, error })
       })
     })
     ....

回答我自己的问题

我写了一个小助手,它创建新的 PassThrough 流,然后在数据进入时写入它们。

const { PassThrough } = require('stream');

// Split stream into $count amount of new streams and return them
const splitStream = (stream, count) => {
  const streams = [...Array(count)].map(() => new PassThrough());
  stream.on('data', chunk => {
    streams.map(s => s.push(chunk));
  })
  stream.on('end', chunk => {
    streams.on('end', () => {
      streams.map(s => s.push(null));
    })
  })
 return streams;
}

现在您只需要传递您的新流而不是原始流。

myFn(streams[0]);
myFn(streams[1]);

免责声明:此方法不负责错误处理,可能会导致内存泄漏。您可能需要考虑使用 'stream' 库中的 Pipeline() 包装器。