чтение файла из корзины aws s3 с помощью node fs
Я пытаюсь прочитать файл, который находится в корзине aws s3, используя
fs.readFile(file, function (err, contents) {
var myLines = contents.Body.toString().split('n')
})
Мне удалось загрузить и загрузить файл с помощью node aws-sdk, но я не знаю, как просто прочитать его и проанализировать содержимое.
Вот пример того, как я читаю файл из s3:
var s3 = new AWS.S3();
var params = {Bucket: 'myBucket', Key: 'myKey.csv'}
var s3file = s3.getObject(params)
8 ответов:
У вас есть пара вариантов. Вы можете включить обратный вызов в качестве второго аргумента, который будет вызван с любым сообщением об ошибке и объектом. Этот Пример прямо из документации AWS:
s3.getObject(params, function(err, data) { if (err) console.log(err, err.stack); // an error occurred else console.log(data); // successful response });
В качестве альтернативы можно преобразовать выходные данные в поток. В документации 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);
Это сделает его:
new AWS.S3().getObject({ Bucket: this.awsBucketName, Key: keyName }, function(err, data) { if (!err) console.log(data.Body.toString()); });
Поскольку вы, кажется, хотите обрабатывать текстовый файл 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() { });
Я еще не мог понять, почему, но
createReadStream
/pipe
подход не сработал для меня. Я пытался загрузить большой CSV-файл (300 МБ+), и я получил дублированные строки. Это казалось случайным вопросом. Окончательный размер файла менялся при каждой попытке загрузить его.В итоге я использовал другой способ, основанный на примерах 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();
Вот пример, который я использовал для повторного поиска и анализа данных json из 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 ...... } });
У меня была точно такая же проблема при загрузке из S3 очень больших файлов.
Пример решения из AWS docs просто не работает:
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
обратный вызов по какой-то причине. Смотрите здесь об этом.Я использую это решение также для записи архивов в 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();
Если вы хотите сохранить память и хотите получить каждую строку как объект 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'); });
Я предпочитаю
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); } } );
Comments