0

Je dois télécharger plusieurs fichiers à partir du compartiment S3 en utilisant node.js. Pour cela, je dois écrire un for loop & appeler la méthode s3.getObject(param) pour télécharger. Une fois les fichiers téléchargés, je dois fusionner leur contenu.Comment télécharger un fichier à partir du compartiment Amazon S3 dans node.js de façon synchrone

J'ai écrit comme ceci:

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. 

Mais comme s3.getObject est un appel asynchrone le thread courant se déplace sur & rien est ajouté à la fileContentList pendant que je fais la fusion.

Comment puis-je résoudre le problème? Une idée?
Est-ce leur méthode synchrone dans aws-sdk pour télécharger le fichier?

Répondre

0

J'ai résolu en utilisant cela. Bien que je n'ai pas essayé les réponses d'Alexander, Lena & Sébastian Je crois que chacune des réponses mentionnées par eux fonctionnerait également dans ce cas. Beaucoup de grâce à eux pour leur réponse rapide:

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 

    } 
3

promesses est mieux,

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); 
}); 
0

Vous pouvez utiliser ici async chacun, il télécharge tous les fichiers en parallèle. Dans cet exemple, le téléchargement continuera si certains fichiers ont échoué, si vous voulez arrêter le téléchargement des fichiers une fois qu'une erreur est survenue, appelez le rappel avec l'erreur, cela appellera le rappel final immédiatement.

async documentation

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) 
     }); 
} 
0

Gardez une trace de téléchargements vous avez démarrées dans une liste séparée et que chaque téléchargement terminé vérifier pour voir si elles sont toutes faites.

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); 
    } 
); 
} 

Une solution plus élégante, si vous ne souhaitez que de fusionner les fichiers si tous les téléchargements terminent avec succès:

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(); 
    } 
); 
}