使用节点fs从aws s3存储桶中读取文件

我试图读取aws s3存储桶中使用的文件

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

我已经能够使用节点aws-sdk下载和上传一个文件,但是我不知道如何简单地阅读和parsing内容。

这里是我从s3读取文件的一个例子:

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

你有几个选项。 你可以包含一个callback作为第二个参数,它将被任何错误信息和对象调用。 这个示例直接来自AWS文档:

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

或者,您可以将输出转换为stream。 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); 

这将做到这一点:

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

由于您似乎想要逐行处理S3文本文件。 以下是使用标准readline模块和AWS'createReadStream()的Node版本

 const readline = require('readline'); const rl = readline.createInterface({ input: s3.getObject(params).createReadStream() }); rl.on('line', function(line) { console.log(line); }) .on('close', function() { }); 

我不明白为什么,但createReadStream / pipe方法不适合我。 我试图下载一个大的CSV文件(300MB +),我得到了重复的行。 这似乎是一个随机问题。 每次尝试下载最终文件大小都不相同。

我最终使用另一种方式,基于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(); 

这样,它就像一个魅力。

这里是我用来从s3中检索和分析json数据的例子。

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

从S3非常大的文件下载时,我有完全相同的问题。

AWS文档的示例解决scheme不起作用:

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

虽然这个解决scheme将工作:

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

由于某种原因, createReadStream尝试不会触发endcloseerrorcallback。 在这里看到这个。

我正在使用该解决scheme将档案写入gzip,因为第一个(AWS示例)在这种情况下不起作用:

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