私はを使用してaws s3バケットにあるファイルを読み取ろうとしています
fs.readFile(file, function (err, contents) {
var myLines = contents.Body.toString().split('\n')
})
ノードaws-sdkを使用してファイルをダウンロードおよびアップロードできましたが、単純にそれを読み取って内容を解析する方法がわかりません。
S3からファイルを読み取る方法の例を次に示します。
var s3 = new AWS.S3();
var params = {Bucket: 'myBucket', Key: 'myKey.csv'}
var s3file = s3.getObject(params)
いくつかのオプションがあります。 2番目の引数としてコールバックを含めることができます。これは、エラーメッセージとオブジェクトとともに呼び出されます。これは 例 は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({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);
これはそれを行います:
new AWS.S3().getObject({ Bucket: this.awsBucketName, Key: keyName }, function(err, data)
{
if (!err)
console.log(data.Body.toString());
});
S3テキストファイルを1行ずつ処理したいようです。これは、標準の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
......
}
});
メモリを節約し、各行をjsonオブジェクトとして取得する場合は、 fast-csv
を使用してreadstreamを作成し、次のように各行をjsonオブジェクトとして読み取ることができます。
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');
});
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
試行は、何らかの理由でend
、close
、またはerror
コールバックを起動しません。これについては here をご覧ください。
最初のアーカイブ(AWSの例)もこの場合は機能しないため、アーカイブをgzipに書き込むためにもこのソリューションを使用しています。
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();
Buffer.from(data.Body).toString('utf8')
を好みます。エンコードパラメータをサポートします。他のAWSサービス(例:Kinesis Streams)では、誰かが'utf8'
エンコーディングを'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);
}
}
);