2014-12-04 121 views
39

我试图读取使用读取AWS S3存储使用节点文件FS

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

我已经能够下载和使用节点aws-上传文件的文件是在AWS S3存储桶sdk,但我对如何简单阅读并解析内容感到茫然。

下面是我如何从S3读取该文件的例子:

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

contents.Body.toString(),而不是内容.Body – Jason 2016-04-20 00:00:37

回答

53

你有几个选项。您可以包含一个回调作为第二个参数,该参数将被任何错误消息和对象调用。这example是直接从AWS文档:

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

或者,您可以将输出转换成流。另外还有AWS文档中的example

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

如果我还希望使用Promise来更好地进行整体异步处理,该怎么办? – verveguy 2016-08-24 03:17:37

+7

@verveguy您可以使用以下内容:'new Promise((resolve,reject)=> {s3.getObject(params).createReadStream()。on('end',()=> {return resolve();}) .on('error',(error)=> {return reject(error);})。pipe(file)});' – 2016-09-29 13:37:29

+1

@verveguy根据您运行的节点版本,aws-sdk版本> 2.3 .0,将使用原生承诺。您还可以明确配置您想要使用的承诺库。 'if(typeof Promise ==='undefined'){ console.log(“使用Bluebird作为承诺”); AWS.config.setPromisesDependency(require('bluebird')); }' – alexhb 2016-11-23 19:29:44

24

这将做到这一点:

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

使用console.log而不是警报nodejs – dpineda 2015-06-23 20:35:11

+3

这不是关键人物,重要的是,OP所需要的是存储在data.Body中,而不仅仅是在数据中(正如其他答案所建议的那样)。我敢肯定,OP将取代任何他需要的警报。 – 2015-06-25 07:23:57

+0

是的,但如果你不测试你的sniped代码尝试elavorete描述 – dpineda 2015-06-25 15:46:01

14

因为你似乎要处理的S3文本文件行由行。下面是使用标准的readline模块和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

一个美妙的记忆保护程序。谢谢! – 2016-07-05 20:10:55

+1

我认为'end'事件被称为'close'。 https://nodejs.org/api/readline.html#readline_event_close – 2017-01-13 20:56:33

+1

如果你想处理gzip源文件,你可以使用s3.getObject(params).createReadStream()。pipe(zlib.createGunzip())'as InputStream以及... – Tobi 2018-01-17 20:55:55

3

这里是我用以检索和从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 
      ...... 
    } 
    }); 
+0

这会减慢我的代码,当json_data是一个大的json数组... – 2016-12-02 05:41:35

5

我想不出为什么呢,但createReadStream/pipe做法并没有为我工作。我试图下载一个大的CSV文件(300MB +),我得到了重复的行。这似乎是一个随机问题。每次尝试下载最终文件大小都会有所不同。

最后我用另一种方式的基础上,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(); 

这样一来,它的工作就像一个魅力。

2

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

从AWS文档中的示例解决方案是行不通的:

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

虽然这种解决方案将工作:

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尝试只是不火的endcloseerror回调一些原因。关于这个请看here

我使用的解决方案也为档案写下来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(); 
相关问题