代码之家  ›  专栏  ›  技术社区  ›  Bilal

Nodejs在循环中下载s3图像(getObject)

  •  1
  • Bilal  · 技术社区  · 7 年前

    我正在尝试循环下载S3 bucket中的图像。我的bucket不是公共的,使用直接getSignedURL不起作用(禁止的错误)。我需要在用户从用户界面选择后从S3下载(10-30)个图像(然后在创建GIF后删除)。

    它下载的图像数量正确(名称正确),但所有图像的内容都将替换为本地计算机上的最后一个图像。我甚至承诺在循环内调用(希望每个getObject调用都能在进行下一次调用之前先完成),但没有成功。除了蓝鸟,我尝试了 this ,但结果相同。我的代码如下所示:

    var urlParams = {Bucket: 'bucket_name', Key: ''};
      for (i = 0; i < imageNames.length; i+=increment) {
        urlParams.Key = imageNames[i]+'.jpg';
        pathToSave = '/local-files/'+urlParams.Key;
    
        var tempFile = fs.createWriteStream(pathToSave);
        // I tried a Promise (and setTimeout) here too but gives me the same result
        var stream = s3.getObject(urlParams).createReadStream().pipe(tempFile);
        var had_error = false;
        stream.on('error', function(err){
          had_error = true;
        });
        stream.on('close', function(){
          if (!had_error) {
            console.log("Image saved");        
          } 
        });    
      }
    

    上述代码完成后,如我所述,所有具有正确名称的图像都会被保存,但由于此处存在非阻塞问题,所有图像都包含数组中最后一个图像的内容(imageNames)。我写下并尝试过的承诺如下

    function getBucketObject(urlParams){
        return  new Promise ((resolve, reject)=> { 
          var pathToSave = '/local-files/'+params.Key;
          var tempFile = fs.createWriteStream(pathToSave);
          var stream = s3.getObject(params).createReadStream().pipe(tempFile);
          var had_error = false;
          stream.on('error', function(err){
            had_error = true;
          });
          stream.on('close', function(){
            if (!had_error) {
              resolve(pathToSave);
            } 
          });
        })
    }
    

    setTimeout和Promise都不能解决我的问题。任何帮助都将不胜感激。谢谢

    2 回复  |  直到 7 年前
        1
  •  1
  •   Anshuman Jaiswal    7 年前

    您应该使用 let 而不是 var

    将代码修改为:

    for (var i = 0; i < imageNames.length; i+=increment) {
        let urlParams = {Bucket: 'bucket_name', Key: imageNames[i]+'.jpg'};
        let pathToSave = 'img/analysis/'+urlParams.Key;
        getBucketObject(urlParams).then(function(pathToSave){
          console.log("image saved");
        })
    }
    
    function getBucketObject(urlParams){
        return  new Promise ((resolve, reject)=> { 
          let pathToSave = '/local-files/'+params.Key;
          let tempFile = fs.createWriteStream(pathToSave);
          let stream = s3.getObject(params).createReadStream().pipe(tempFile);
          let had_error = false;
          stream.on('error', function(err){
            had_error = true;
          });
          stream.on('close', function(){
            if (!had_error) {
              resolve(pathToSave);
            } 
          });
        })
    }
    
        2
  •  0
  •   Bilal    7 年前

    按照@Anshuman Jaiswal在评论中的建议,我尝试了使用let而不是var的代码,现在就可以了。谢谢Anshuman。循环中的代码如下所示

    for (var i = 0; i < imageNames.length; i+=increment) {
        let urlParams = {Bucket: 'bucket_name', Key: imageNames[i]+'.jpg'};
        let pathToSave = '/local-files/'+urlParams.Key;
        getBucketObject(urlParams).then(function(pathToSave){
          console.log("image saved");
        })
      }
    

    承诺函数如下

    function getBucketObject(urlParams){
        return  new Promise ((resolve, reject)=> { 
          let pathToSave = '/local-files/'+params.Key;
          let tempFile = fs.createWriteStream(pathToSave);
          let stream = s3.getObject(params).createReadStream().pipe(tempFile);
          let had_error = false;
          stream.on('error', function(err){
            had_error = true;
          });
          stream.on('close', function(){
            if (!had_error) {
              resolve(pathToSave);
            } 
          });
        })
    }