2017-03-07 1 views
1

Das macht mich verrückt.Kann Dateien von S3 nicht mit nodeJS herunterladen: einige Dateien enden nicht

Ich brauche meinen Server, um 100 relativ kleine Dateien von S3 herunterladen (max 2 MB).

Es funktioniert immer für ~ 95% der Dateien, aber es blockiert für die letzten 6-8 Dateien. Die resolve noch die reject Rückruf wird nie genannt ...

Ich habe versucht, Dateien parallel zum Download ...

  • Wer dies erlebt?
  • Könnte es sein, dass ein Paket verloren geht und der Stream nicht schließt?
  • Gibt es eine maximale Anzahl gleichzeitiger Downloads?

Hier ist der Code, der in 95% der Fälle technisch funktioniert:

let singleGetFromS3 = (bucket, fileName) => { 
    return new Promise((resolve, reject) => { 
     let extension = getFileNameExtension(fileName); 
     fs.stat(`./${fileName}`, (err, stat) => { 
     if (err === null) { 
      console.log(`${fileName} exists locally`); 
      resolve(fileName); 
     } else if(err.code === 'ENOENT') { 
      let params = {Bucket: bucket, Key: fileName}; 
      let file = require('fs').createWriteStream(`./tmp-${fileName}`); 
      s3.getObject(params).createReadStream() 
      .on('error', (error) => { return reject(error); }) 
      .on('end',() => { 
       fs.rename(`./tmp-${fileName}`, `./${fileName}`, reject); 
       return resolve(fileName); 
      }) 
      .pipe(file); 
     } else { 
      reject(err); 
     } 
     }); 
    }); 
    }; 

Verwendung:

"aws-sdk": "^2.23.0", 
node --version 
v4.5.0 

Antwort

2

Sieht aus wie Sie für das falsche Ereignis hören, wann zu lösen. Sie wollen nicht auflösen, wenn alle Bytes von S3's Readable gelesen wurden, die Sie auflösen möchten, wenn file schreibend ist.

let singleGetFromS3 = (bucket, fileName) => { 
    return new Promise((resolve, reject) => { 
     let extension = getFileNameExtension(fileName); 
     fs.stat(`./${fileName}`, (err, stat) => { 
     if (err === null) { 
      console.log(`${fileName} exists locally`); 
      resolve(fileName); 
     } else if(err.code === 'ENOENT') { 
      let params = {Bucket: bucket, Key: fileName}; 
      let file = require('fs').createWriteStream(`./tmp-${fileName}`);  

      // Listen for the file to be done writing, then resolve 
      file.on('finish',() => { 
       fs.rename(`./tmp-${fileName}`, `./${fileName}`, reject); 
       return resolve(fileName); 
      }) 

      s3.getObject(params).createReadStream() 
      .on('error', (error) => { return reject(error); }) 
      .pipe(file); 
     } else { 
      reject(err); 
     } 
     }); 
    }); 
    }; 
+0

Danke. Ich dachte darüber nach, dachte aber nicht an einen Grund, warum der 'WriteStream' sich selbst schließen sollte. Aber anscheinend funktioniert es, obwohl ich noch 5 ~ 6 Akten habe, die nicht abschließen .... :(:( –

+0

Übrigens bin ich sehr erstaunt, um zu finden, dass solch triviale Operation in S3 solch ein Schmerz im KnotenJS ist ... –

+0

@AugustinRiedinger Wenn Sie dies vereinfachen möchten, würde ich damit beginnen, Callbacks, Events/Streams und Promises nicht alle in der gleichen Funktion zu verwenden.Sie sollten bluebird.js verwenden, um '' '' '' 'zu promisifizieren, so dass Sie nicht Ich brauche den 'fs.stat()' Callback. Auch habe ich die Antwort bearbeitet, verwende nicht das '' close'' Ereignis, das ich ursprünglich gesetzt habe, sondern '' finish''. – peteb

Verwandte Themen