2

我必须使用 node.js 从 S3 存储桶下载多个文件。为此,我必须编写一个for loop& 调用s3.getObject(param)方法来下载。下载文件后,我必须合并它们的内容。

我是这样写的:

var fileContentList = new ArrayList();

for(i=0; i<fileNameList.length i++){
    s3.getObject({ Bucket: "my-bucket", Key: fileNameList.get(i) }, function (error, data) {
    if (error != null) {
      alert("Failed to retrieve an object: " + error);
    } else {
      alert("Loaded " + data.ContentLength + " bytes");
      fileContentList.add(data.Body.toString());
    }
  }
);
}

//Do merging with the fileContentList.

但是作为s3.getObject异步调用,当前线程继续前进,fileContentList在我进行合并时没有添加任何内容。

我该如何解决这个问题?任何想法?
他们在 aws-sdk 中是否有任何同步方法来下载文件?

4

4 回答 4

8

承诺是更好的方式,

var getObject = function(keyFile) {
    return new Promise(function(success, reject) {
        s3.getObject(
            { Bucket: "my-bucket", Key: keyFile },
            function (error, data) {
                if(error) {
                    reject(error);
                } else {
                    success(data);
                }
            }
        );
    });
}

var promises = [];
var fileContentList = new ArrayList();

for(i=0; i<fileNameList.length i++){
    promises.push(getObject(fileNameList.get(i)));
}

Promise.all(promises)
.then(function(results) {
    for(var index in results) {
        var data = results[index];
        fileContentList.add(data.Body.toString());
    }
    // continue your process here
})
.catch(function(err) {
    alert(err);
});
于 2017-07-02T08:06:53.500 回答
1

我已经解决了这个问题。虽然我没有尝试过 Alexander、Lena 和 Sébastian 的答案,但我相信他们提到的每个答案在这种情况下也适用。非常感谢他们的快速回复:

Async.eachSeries(casCustomersList, function (customerName, next){
        if(casCustomersList.length>0 && customerName != customerId) {

            var paramToAws = {
                Bucket: bucketName,
                Key: folderPath +'applicationContext-security-' + customerName + '.xml'      //file name
            };
            AWSFileAccessManager.downloadFile(paramToAws, function (error, result) {
                if (error) {
                    next(error);
                } else {
                    customerApplicationContext.add(result.Body.toString());
                    next();
                }

            });
        } else{
            next();
        }

    }, function(err) {
       //Write the rest of your logic here to process synchronously as it is the callback function

    }
于 2017-07-24T14:43:10.657 回答
0

您可以在此处使用 async each,它将并行下载所有文件。在此示例中,如果某些文件失败,下载将继续,如果您想在发生错误后停止下载文件,请使用错误调用回调,这将立即调用最终回调。

异步文档

var async = require('async');
var fileContentList = new ArrayList();
function downloadS3Multiple(done){
    async.each([
            function (callback) {
                s3.getObject({Bucket: "my-bucket", Key: fileNameList.get(i)}, function (err, res) {
                    if (err) {
                        alert("Failed to retrieve an object: " + error);
                        callback();
                    }
                    else {
                        alert("Loaded " + data.ContentLength + " bytes");
                        fileContentList.add(data.Body.toString());
                        callback();

                    }
                })
            }
        ], function (err, results) {
            done(err, fileContentList)
        });
}
于 2017-07-02T08:12:37.777 回答
0

在单独的列表中跟踪您启动的下载,并在每次下载完成时检查它们是否全部完成。

var fileContentList = new ArrayList();
var completedList = new ArrayList();
// function to setDone and initiate merge if all download attempts completed.
function setDone(i) {
    completedList[i]=true;
    var allDone= true;
    for(i=0; i<completedList.length && allDone=completedList[i] && allDone; i++);
    if(allDone) {
       mergeFiles();
    }
}

// fill completedList with a false value for each fill to be downloaded
for(i=0; i<fileNameList.length;i++) completedList.add(false);

// initiate the downloads
for(i=0; i<fileNameList.length; i++){
    s3.getObject({ Bucket: "my-bucket", Key: fileNameList.get(i) }, function (error, data) {
    if (error != null) {
      alert("Failed to retrieve an object: " + error);
    } else {
      alert("Loaded " + data.ContentLength + " bytes");
      fileContentList.add(data.Body.toString());
    }
    setDone(i);
  }
);
}

一个更优雅的解决方案,如果您只想在所有下载成功完成后合并文件:

var fileContentList = new ArrayList();

for(i=0; i<fileNameList.length i++){
    s3.getObject({ Bucket: "my-bucket", Key: fileNameList.get(i) }, function (error, data) {
    if (error != null) {
      alert("Failed to retrieve an object: " + error);
    } else {
      alert("Loaded " + data.ContentLength + " bytes");
      fileContentList.add(data.Body.toString());
    }
    if(fileContentList.length==fileNameList.length) combineFiles();
  }
);
}
于 2017-07-02T08:17:40.623 回答