首页 文章

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

提问于
浏览
3

我正在使用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

1 回答

  • 8

    除了检查客户端的 Content-Type 标头's request, I' m之外,我不知道检查MIME类型的更好,更聪明的方法 .

    您可以使用Transform stream实现上述解决方案 . 在此示例中,转换流缓冲一些任意数量的数据,然后将其发送到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();
        });
      }
    };
    

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

    // Usage example
    var fs = require('fs');
    fs.createReadStream('input.txt').pipe(mimeChecker).pipe(fs.createWriteStream('output.txt'));
    

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

相关问题