【问题标题】:Node.js express + busboy file type checkNode.js express + busboy 文件类型检查
【发布时间】:2015-11-28 17:45:41
【问题描述】:

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

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

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

现在我正努力让这项工作尽可能高效,但这是我苦苦挣扎的地方: 我想直接将文件流通过管道传输到天蓝色。但在此之前,我需要将流中的前 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 上传完成”之后大约 30 到 60 秒出现,可能是由于一些超时。

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

【问题讨论】:

    标签: node.js azure express stream busboy


    【解决方案1】:

    您无需在混合中添加额外的流。只需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();
    });
    

    【讨论】:

    • 非常感谢!很好的解决方案。只是检查文件类型有一个小错误,该行应该是:if (type.ext === 'jpg' || type.ext === 'png' || type.ext === 'gif') {Thanks!
    • 还有一件奇怪的事情,也许你也可以帮我解决一下:请求的 URL 的快速控制台输出仍然延迟 30-60 秒。我刚刚意识到当我直接将文件流式传输到 azure 时也会发生这种情况。知道为什么会这样吗?我需要关闭文件流吗?
    • 忘记最后一个问题:我从未使用 res.json() 或其他 res.* 函数发送过响应。我认为这导致了延误。我稍后会对此进行测试。
    猜你喜欢
    • 1970-01-01
    • 2015-03-23
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 2014-04-15
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多