验证node.js中上传文件的mime类型

chm*_*nie 3 multipartform-data stream node.js mime-types express

我正在使用node和express来处理文件上传,我正在使用multiparty/busboy和request将它们直接传输到转换服务.

有没有办法在将流发送到相应的提供程序之前验证流是否具有某些特定的文件类型?我尝试了https://github.com/mscdex/mmmagic从第一个块中获取MIME类型,并且它工作得很好.我想知道以下工作流程是否可能以某种方式工作:

  • 缓冲文件上载流并检查Mime类型的传入数据.
  • 检查前几个块并且mime类型正确时,将缓冲区清空到请求流中.
  • 当mime类型结果不正确时,发送错误消息并返回.

我试图让这个工作,但我似乎有一些流兼容性问题(节点0.8.x与节点0.10.x流,请求库不支持).

有没有最佳实践来解决这个问题?我看错了吗?

编辑:感谢Paul,我想出了这段代码:

https://gist.github.com/chmanie/8520572

Pau*_*gel 8

除了检查Content-Type客户端请求的标头之外,我还没有意识到检查MIME类型的更好,更聪明的方法.

您可以使用转换流实现上述解决方案.在此示例中,转换流缓冲一些任意数量的数据,然后将其发送到MIME检查库.如果一切正常,它会重新发出数据.随后的块将按原样发出.

var stream = require('readable-stream');
var mmm = require('mmmagic');
var mimeChecker = new stream.Transform();
mimeChecker.data = [];
mimeChecker.mimeFound = false;
mimeChecker._transform = function (chunk, encoding, done) {
  var self = this;

  if (self.mimeFound) {
    self.push(chunk);
    return done();
  }

  self.data.push(chunk);
  if (self.data.length < 10) {
    return done();
  }
  else if (self.data.length === 10) {
    var buffered = Buffer.concat(this.data);
    new mmm.Magic(mmm.MAGIC_MIME_TYPE).detect(buffered, function(err, result) {
      if (err) return self.emit('error', err);
      if (result !== 'text/plain') return self.emit('error', new Error('Wrong MIME'));
      self.data.map(self.push.bind(self));
      self.mimeFound = true;
      return done();
    });
  }
};
Run Code Online (Sandbox Code Playgroud)

然后,您可以将此转换流传输到任何其他流,例如请求流(顺便说一下,它完全支持节点0.10流).

// Usage example
var fs = require('fs');
fs.createReadStream('input.txt').pipe(mimeChecker).pipe(fs.createWriteStream('output.txt'));
Run Code Online (Sandbox Code Playgroud)

编辑:为了更清楚地了解您在Node 0.8和0.10流之间遇到的不兼容性,当您定义流并将其附加到.on('data')监听器时,它将切换到流模式(也称为0.8流),这意味着它将发送数据,即使目的地没有听.如果您启动异步请求,则可能会发生这种情况Magic.detect():数据仍在流动,即使您正在监听它.