node.js - 大文件上传到 Azure blob 在 Node.js 中处理

标签 node.js azure azure-blob-storage node.js-stream

我的目标是将大文件(任何文件类型)上传到 Azure blob。

我想遵循以下两种方法。

1. Convert file into stream and upload into Azure blob
2. Convert file into block streams and commit all the blocks to Azure blob in parallel

我正在使用 Node.js Azure blob 服务 API

方法 1: 我正在使用 fs.createReadStream(fileName, 'utf-8') 将文件转换为 ReadStream。并使用 blobService.createBlockBlobFromStream() 将该流上传到 Azure blob。 以下是此方法的示例代码

    var blobName = "azure-blob-name.doc";
    var fileSize = fs.statSync(fileName).size;
    var readableStream = fs.createReadStream(fileName, 'utf-8');
        blobService.createBlockBlobFromStream(containerName, blobName, readableStream, fileSize, function (error, result, response) { 
            if(error) console.log(error);
            console.log({message : "blob uploaded"});
        });

方法 2: 我想使用 blobService.createBlockFromStream()ReadStream 转换为 azure blob block ,并并行提交所有 block 。我怎样才能实现这种方法?

下面是我尝试执行的示例代码,但最终抛出了错误

var fileName = "local-file-path/filename.doc";
    var blobName = "azure-blob-name.doc";
    var fileSize = fs.statSync(fileName).size;
    var readableStream = fs.createReadStream(fileName, 'utf-8');
    var bl=1;
    var blockIds = [];
    readableStream.on("data", function (chunk) {
        var blockId = 'block'+bl;
        bl++;
        blobService.createBlockFromStream(blockId, containerName, blobName, chunk, chunk.length, function(error, response){
            if(error) console.log(error);

            blockIds.push(blockId);
                    console.log({message : "block created"});
        });
    });

下面是我收到的错误

    D:\main-workspace\file-management\node_modules\azure-storage\lib\common\services\storageserviceclient.js:522
                body.outputStream.on('open', function () {
                                  ^
    TypeError: body.outputStream.on is not a function
  1. 方法 1 工作正常,但上传时间过长。 (统计数据:上传 40 MB 文件需要 80 秒)。
  2. 我的第二种方法是提高性能的正确方法吗?如果是,我怎样才能实现这种方法?

有没有更好的方法来提高性能?在这方面有什么建议吗?

除了 Azure Blob 服务 API 之外,我们还有其他方法可以做到这一点吗?我的目标是在更短的时间内上传任何类型的大文件。例如,40 MB 的文件必须在 20 秒内上传。

请带我朝正确的方向前进。感谢您提前回复。

编辑 - 更新代码

@Gaurav

下面是我更新的代码。但我的 readableStream.on("end", function(){}) 永远不会被调用来提交 block 。在我的 Azure 帐户中,文件正在创建,但大小为 0 字节

      const stream = require('stream');
      var fileName = "local-file-path/filename.doc";
      var blobName = "azure-blob-name.doc";
      var fileSize = fs.statSync(blobName).size;
      var customBlockSize = 1200; //1.2 MB CAP           
      var NoOfBlocks = Math.ceil(fileSize/customBlockSize);
      var blockIdLength = NoOfBlocks.toString().length;
      var readableStream = fs.createReadStream(fileName, 'utf-8');
      var bl=1;
      var blockIds = [];
      readableStream.on("data", function (chunk) {         
          var blockId = 'block'+ blockGuId(bl, blockIdLength);//Block ids must be of same length
          bl++;
          const bufferStream = new stream.PassThrough({
            highWaterMark: chunk.length
          });
          bufferStream.end(chunk);
          blobService.createBlockFromStream(blockId, containerName, blobName, bufferStream, chunk.length, function(error, response){
              if(error) console.log(error);

              blockIds.push(blockId);
              console.log({message : "block ("+blockId+") created"});
          });
      });

      readableStream.on("end", function(){

        console.log('readableStream.on "end"');

        blobService.commitBlocks(containerName, blobName, blockIds, function(error, result){
          if(error) console.log(error);

          console.log({message : "all blocks uploaded"});
          var hrend = process.hrtime(hrstart)
          console.info('Execution time (sec ms): %ds %dms', hrend[0], hrend[1] / 1000000)
        });
      });

      blockGuId(number, blockIdLength)
      {
        return Array(Math.max(blockIdLength - String(number).length + 1, 0)).join(0) + number;
      }

下面是套接字错误

{ Error: socket hang up at createHangUpError (_http_client.js:323:15) at TLSSocket.socketCloseListener (_http_client.js:364:25) at TLSSocket.emit (events.js:187:15) at _handle.close (net.js:610:12) at TCP.done (_tls_wrap.js:386:7) code: 'ECONNRESET' }

我在这里缺少什么?为什么创建区 block 时会出现socket错误?

最佳答案

您可以尝试以下代码吗:

const stream = require('stream');

var fileName = "local-file-path/filename.doc";
    var blobName = "azure-blob-name.doc";
    var fileSize = fs.statSync(fileName).size;
    var readableStream = fs.createReadStream(fileName, 'utf-8');
    var bl=1;
    var blockIds = [];
    readableStream.on("data", function (chunk) {
        //var blockId = 'block'+bl;
        bl++;
        var blockId = UseGuidHere();//Block ids must be of same length
        const bufferStream = new stream.PassThrough({
          highWaterMark: chunk.length
        });
        bufferStream.end(chunk);
        blobService.createBlockFromStream(blockId, containerName, blobName, bufferStream, chunk.length, function(error, response){
            if(error) console.log(error);

            blockIds.push(blockId);
                    console.log({message : "block created"});
        });
    });

如代码中所述,请为您的 block ID 分配一个 GUID,因为 block ID 的长度必须相同。按照您当前的逻辑,在 9 个 block 之后,您的 block id 的长度将发生变化,这将导致上传过程失败。

关于node.js - 大文件上传到 Azure blob 在 Node.js 中处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57265764/

相关文章:

node.js - 为什么 connect-mongo 为每个请求创建新 session ?

azure - 无法确认正在创建任何 Actor

azure - "Get-AzureRmWebApp"需要哪个模块?

apache-spark - 读取过去 2 小时在 Pyspark 中创建的 parquet 文件

angular - 如何使用 v10 SDK 将图像上传到 Azure Blob 存储?

azure - SAS token 中的日期和时间格式

node.js - MongoDb 聚合出现错误

javascript - x.controller 和 .controller 之间的区别

javascript - 配对键/值数组

angularjs - 响应中 'Access-Control-Allow-Credentials' header 的值为 '',当请求的凭据模式为 'true' 时,该值必须为 'include'