web-dev-qa-db-fra.com

lire le fichier du seau aws s3 à l'aide du noeud fs

J'essaie de lire un fichier qui se trouve dans un seau aws s3 en utilisant 

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

J'ai été en mesure de télécharger et de télécharger un fichier à l'aide du noeud aws-sdk, mais je ne sais pas comment le lire simplement et en analyser le contenu.

Voici un exemple de la façon dont je lis le fichier de s3:

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

Vous avez plusieurs options. Vous pouvez inclure un rappel en tant que second argument, qui sera appelé avec tout message d'erreur et l'objet. Ce exemple provient directement de la documentation AWS:

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

Vous pouvez également convertir la sortie en flux. Il y a aussi un exemple dans la documentation AWS:

var s3 = new AWS.S3({apiVersion: '2006-03-01'});
var params = {Bucket: 'myBucket', Key: 'myImageFile.jpg'};
var file = require('fs').createWriteStream('/path/to/file.jpg');
s3.getObject(params).createReadStream().pipe(file);
71
dug

Cela va le faire:

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

Puisque vous semblez vouloir traiter un fichier texte S3 ligne par ligne. Voici une version de nœud qui utilise le module readline standard et la commande createReadStream () d'AWS.

const readline = require('readline');

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

rl.on('line', function(line) {
    console.log(line);
})
.on('close', function() {
});
18
Jason

Je ne comprenais pas encore pourquoi, mais l'approche createReadStream/pipe ne fonctionnait pas pour moi. J'essayais de télécharger un gros fichier CSV (300 Mo +) et j'ai eu des lignes dupliquées. Cela semblait un problème aléatoire. La taille du fichier final variait à chaque tentative de téléchargement.

J'ai fini par utiliser un autre moyen, basé sur exemples AWS JS SDK :

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

De cette façon, cela a fonctionné comme un charme.

6
Gustavo Straube

voici l'exemple avec lequel j'ai utilisé pour récupérer et analyser les données JSON de 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
           ......
     }
   });
4
devendra

Si vous souhaitez économiser de la mémoire et obtenir chaque ligne en tant qu'objet json, vous pouvez utiliser fast-csv pour créer un flux de lecture et lire chaque ligne en tant qu'objet json comme suit:

const csv = require('fast-csv');
const AWS = require('aws-sdk');

const credentials = new AWS.Credentials("ACCESSKEY", "SECRETEKEY", "SESSIONTOKEN");
AWS.config.update({
    credentials: credentials, // credentials required for local execution
    region: 'your_region'
});
const dynamoS3Bucket = new AWS.S3();
const stream = dynamoS3Bucket.getObject({ Bucket: 'your_bucket', Key: 'example.csv' }).createReadStream();

var parser = csv.fromStream(stream, { headers: true }).on("data", function (data) {
    parser.pause();  //can pause reading using this at a particular row
    parser.resume(); // to continue reading
    console.log(data);
}).on("end", function () {
    console.log('process finished');
});
2
kgangadhar

J'ai eu exactement le même problème lors du téléchargement à partir de très gros fichiers S3.

L'exemple de solution de AWS docs ne fonctionne tout simplement pas:

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

Alors que cette solution fonctionnera:

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

La tentative createReadStream ne déclenche pas le rappel end, close ou error pour une raison quelconque. Voir ici à ce sujet.

J'utilise cette solution également pour écrire des archives dans gzip, car le premier (exemple AWS) ne fonctionne pas dans ce cas non plus:

        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();
2
loretoparisi

Je préfèreBuffer.from(data.Body).toString('utf8'). Il supporte les paramètres de codage. Avec d'autres services AWS (par exemple, Kinesis Streams), il peut être utile de remplacer le codage 'utf8' par 'base64'.

new AWS.S3().getObject(
  { Bucket: this.awsBucketName, Key: keyName }, 
  function(err, data) {
    if (!err) {
      const body = Buffer.from(data.Body).toString('utf8');
      console.log(body);
    }
  }
);
0
Costin