Node.js表达+ busboy文件类型检查

时间:2015-11-28 17:45:42

标签: node.js azure express stream busboy

我正在尝试使用express与busboy在Node.js 4.x中实现文件上传。 我已经能够上传文件并将它们存储在Azure Blob存储中。

不,我想在将文件存储到Azure之前验证文件类型,并拒绝任何无效的文件。

我想使用魔术数字进行验证。我发现 const fileType = require('file-type');确定我的文件类型。

现在我正努力让这项工作尽可能高效,但这里是我在努力的地方: 我想直接将文件流传输到azure。但在此之前,我需要将流中的前5个字节读入缓冲区,该缓冲区由文件类型处理。

从流中读取然后管道到azure肯定不起作用。经过一些研究后,我通过在2个PassThrough流中管理文件找到了解决方案。但现在我正在努力正确处理这两个流。

const fileType = require('file-type');
const pass = require('stream').PassThrough;

//...

req.busboy.on('file', function (fieldname, file, filename) {
   console.log("Uploading: " + filename);
   var b = new pass;
   var c = new pass;
   file.pipe(b);
   file.pipe(c);


   var type = null;
   b.on('readable', function() {
      b.pause();
      if(type === null) {
         var chunk = b.read(5);
         type = fileType(chunk) || false;
         b.end();
      }
   });

   b.on('finish', function() {
      if(type && ['jpg', 'png', 'gif'].indexOf(type.ext) !== -1) {
         var blobStream = blobSvc.createWriteStreamToBlockBlob(storageName,
            blobName,
            function (error) {
               if (error) console.log('blob upload error', error);
               else console.log('blob upload complete')
            });
         c.pipe(blobStream);
      }
      else {
         console.error("Rejected file of type " + type);
      }
   });

});

此解决方案有时会起作用 - 有时会出现一些“写后结束”错误。 此外,我认为流没有正确关闭,因为通常,在请求之后,在控制台上记录这样的事情:

POST /path - - ms - -

但是这条日志消息现在在“blob upload complete”之后的30s-60s,可能是由于一些超时。

知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

您无需在混音中添加其他流。只需unshift()消耗的部分返回到流上。例如:

const fileType = require('file-type');
req.busboy.on('file', function (fieldname, file, filename) {
  function readFirstBytes() {
    var chunk = file.read(5);
    if (!chunk)
      return file.once('readable', readFirstBytes);
    var type = fileType(chunk);
    if (type.ext === 'jpg' || type.ext === 'png' || type.ext === 'gif') {
      const blobStream = blobSvc.createWriteStreamToBlockBlob(
        storageName,
        blobName,
        function (error) {
          if (error)
            console.log('blob upload error', error);
          else
            console.log('blob upload complete');
        }
      );
      file.unshift(chunk);
      file.pipe(blobStream);
    } else {
      console.error('Rejected file of type ' + type);
      file.resume(); // Drain file stream to continue processing form
    }
  }

  readFirstBytes();
});