2014-12-04 38 views
39

Sto tentando di leggere un file che si trova in un secchio AWS s3 usandoleggere il file da AWS S3 secchio utilizzando nodo fs

fs.readFile(file, function (err, contents) { 
    var myLines = contents.Body.toString().split('\n') 
}) 

Sono stato in grado di scaricare e caricare un file utilizzando il nodo di aws- sdk, ma non riesco a capire come leggerlo e analizzare il contenuto.

Ecco un esempio di come sto leggendo il file da S3:

var s3 = new AWS.S3(); 
var params = {Bucket: 'myBucket', Key: 'myKey.csv'} 
var s3file = s3.getObject(params) 
+3

contents.Body.toString() al posto dei contenuti .Body – Jason

risposta

53

Hai un paio di opzioni. È possibile includere un callback come secondo argomento, che verrà richiamato con qualsiasi messaggio di errore e l'oggetto. Questo example è retta dalla documentazione AWS:

s3.getObject(params, function(err, data) { 
    if (err) console.log(err, err.stack); // an error occurred 
    else  console.log(data);   // successful response 
}); 

In alternativa, è possibile convertire l'output in un flusso. C'è anche un example nella documentazione AWS:

var s3 = new AWS.S3(); 
var params = {Bucket: 'myBucket', Key: 'myImageFile.jpg'}; 
var file = require('fs').createWriteStream('/path/to/file.jpg'); 
s3.getObject(params).createReadStream().pipe(file); 
+0

Cosa succede se desidero anche utilizzare una Promessa per una migliore gestione asincrona complessiva? – verveguy

+7

@verveguy È possibile utilizzare quanto segue: 'new Promise ((resolve, reject) => {s3.getObject (params) .createReadStream(). On ('end',() => {return resolve();}) .on ('error', (error) => {return reject (error);}). pipe (file)}); ' –

+1

@verveguy A seconda della versione del nodo in esecuzione, la versione di aws-sdk> 2.3 .0, userà le promesse native. È inoltre possibile configurare in modo esplicito quale libreria di promesse si desidera utilizzare. 'if (typeof Promise === 'undefined') { console.log (" Utilizzo di Bluebird for Promises "); AWS.config.setPromisesDependency (require ('bluebird')); } – alexhb

24

Questo lo farà:

new AWS.S3().getObject({ Bucket: this.awsBucketName, Key: keyName }, function(err, data) 
{ 
    if (!err) 
     console.log(data.Body.toString()); 
}); 
+0

utilizza console.log anziché avviso per nodejs – dpineda

+3

che non è il punto man, la cosa importante è che ciò che OP vuole è archiviato in data. Body e non solo nei dati (come suggerito da alcune altre risposte). Sono sicuro che l'OP sostituirà l'avviso con qualunque cosa abbia bisogno di essere. –

+0

Sì, ma se non si prova il codice citato provare ad elavorare una descrizione – dpineda

14

Dal momento che sembra voler elaborare una linea linea per file di testo S3. Ecco una versione nodo che utilizza il modulo readline standard AWS' createReadStream()

const readline = require('readline'); 

const rl = readline.createInterface({ 
    input: s3.getObject(params).createReadStream() 
}); 

rl.on('line', function(line) { 
    console.log(line); 
}) 
.on('close', function() { 
}); 
+1

Un fantastico risparmio di memoria. Grazie! –

+1

Penso che l'evento 'end' sia chiamato' chiudi 'invece. https://nodejs.org/api/readline.html#readline_event_close –

+1

Se vuoi gestire i file sorgente compressi con gzip, puoi usare 's3.getObject (params) .createReadStream(). pipe (zlib.createGunzip())' as Anche InputStream ... – Tobi

3

qui è l'esempio che ho usato per retrive e analizzare dati JSON da s3.

var params = {Bucket: BUCKET_NAME, Key: KEY_NAME}; 
    new AWS.S3().getObject(params, function(err, json_data) 
    { 
     if (!err) { 
     var json = JSON.parse(new Buffer(json_data.Body).toString("utf8")); 

     // PROCESS JSON DATA 
      ...... 
    } 
    }); 
+0

rallenta il mio codice quando json_data è un grande array json ... –

5

non riuscivo a capire il motivo per cui ancora, ma l'approccio createReadStream/pipe non ha funzionato per me. Stavo cercando di scaricare un file CSV di grandi dimensioni (300 MB +) e ho ottenuto linee duplicate. Sembrava un problema casuale. La dimensione del file finale variava a ogni tentativo di scaricarlo.

ho finito per usare un altro modo, in base a AWS JS SDK examples:

var s3 = new AWS.S3(); 
var params = {Bucket: 'myBucket', Key: 'myImageFile.jpg'}; 
var file = require('fs').createWriteStream('/path/to/file.jpg'); 

s3.getObject(params). 
    on('httpData', function(chunk) { file.write(chunk); }). 
    on('httpDone', function() { file.end(); }). 
    send(); 

In questo modo, ha funzionato come un fascino.

2

Ho avuto esattamente lo stesso problema durante il download da file molto grandi S3.

La soluzione esempio dalla documentazione AWS semplicemente non funziona:

var file = fs.createWriteStream(options.filePath); 
     file.on('close', function(){ 
      if(self.logger) self.logger.info("S3Dataset file download saved to %s", options.filePath); 
      return callback(null,done); 
     }); 
     s3.getObject({ Key: documentKey }).createReadStream().on('error', function(err) { 
      if(self.logger) self.logger.error("S3Dataset download error key:%s error:%@", options.fileName, error); 
      return callback(error); 
     }).pipe(file); 

Anche se questa soluzione funziona:

var file = fs.createWriteStream(options.filePath); 
    s3.getObject({ Bucket: this._options.s3.Bucket, Key: documentKey }) 
    .on('error', function(err) { 
     if(self.logger) self.logger.error("S3Dataset download error key:%s error:%@", options.fileName, error); 
     return callback(error); 
    }) 
    .on('httpData', function(chunk) { file.write(chunk); }) 
    .on('httpDone', function() { 
     file.end(); 
     if(self.logger) self.logger.info("S3Dataset file download saved to %s", options.filePath); 
     return callback(null,done); 
    }) 
    .send(); 

Il tentativo createReadStream semplicemente non si attiva la richiamata end, close o error per qualche ragione. Vedi here su questo.

sto usando questa soluzione anche per scrivere gli archivi di gzip, dal momento che il primo (AWS esempio) non funziona in questo caso sia:

 var gunzip = zlib.createGunzip(); 
     var file = fs.createWriteStream(options.filePath); 

     s3.getObject({ Bucket: this._options.s3.Bucket, Key: documentKey }) 
     .on('error', function (error) { 
      if(self.logger) self.logger.error("%@",error); 
      return callback(error); 
     }) 
     .on('httpData', function (chunk) { 
      file.write(chunk); 
     }) 
     .on('httpDone', function() { 

      file.end(); 

      if(self.logger) self.logger.info("downloadArchive downloaded %s", options.filePath); 

      fs.createReadStream(options.filePath) 
      .on('error', (error) => { 
       return callback(error); 
      }) 
      .on('end',() => { 
       if(self.logger) self.logger.info("downloadArchive unarchived %s", options.fileDest); 
       return callback(null, options.fileDest); 
      }) 
      .pipe(gunzip) 
      .pipe(fs.createWriteStream(options.fileDest)) 
     }) 
     .send(); 
Problemi correlati