노드 fs를 사용하여 aws s3 버킷에서 파일 읽기


79

다음을 사용하여 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)

4
contents.Body 대신 contents.Body.toString ()
Jason

답변:


90

몇 가지 옵션이 있습니다. 두 번째 인수로 콜백을 포함 할 수 있으며, 이는 오류 메시지 및 객체와 함께 호출됩니다. 이 예제 는 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);

더 나은 전체 비동기 처리를 위해 Promise를 사용하려면 어떻게해야합니까?
verveguy

16
: @verveguy 당신은 다음과 같은 사용할 수 있습니다new Promise((resolve, reject) => {s3.getObject(params).createReadStream().on('end', () => { return resolve(); }).on('error', (error) => { return reject(error); }).pipe(file)});
구스타보 Straube

1
@verveguy 실행중인 노드의 버전에 따라 aws-sdk 버전> 2.3.0은 기본 약속을 사용합니다. 사용하려는 promise 라이브러리를 명시 적으로 구성 할 수도 있습니다. if (typeof Promise === 'undefined') { console.log("Using Bluebird for Promises"); AWS.config.setPromisesDependency(require('bluebird')); }
alexhb

pipe ()가 종료되었는지 어떻게 알 수있어 로컬에서 파일을 작성한 후 다른 작업을 할 수 있습니다 ...?
오사마

46

이렇게하면됩니다.

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

24

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

1
대신 end이벤트가 호출 되었다고 생각합니다 close. nodejs.org/api/readline.html#readline_event_close
Jonathan Morales Vélez

3
당신은 gzip으로 압축 된 소스 파일을 처리하려면, 당신이 사용할 수 s3.getObject(params).createReadStream().pipe(zlib.createGunzip())의 InputStream뿐만 아니라 ...
토비

8

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

8

아직 이유를 알 수 없었지만 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();

이렇게하면 마치 매력처럼 작동했습니다.


5

나는 선호한다 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);
    }
  }
);

4

메모리를 절약하고 각 행을 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');
});

3

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어떤 이유로 콜백. 이것에 대해 여기 를 참조 하십시오 .

첫 번째 (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();

2

새 버전의 sdk에서는 수락 된 답변이 작동하지 않으며 객체가 다운로드 될 때까지 기다리지 않습니다. 다음 코드 스 니펫은 새 버전에 도움이됩니다.

// dependencies

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

// get reference to S3 client

const s3 = new AWS.S3();

exports.handler = async (event, context, callback) => {

var bucket = "TestBucket"

var key = "TestKey"

   try {

      const params = {
            Bucket: Bucket,
            Key: Key
        };

       var theObject = await s3.getObject(params).promise();

    } catch (error) {
        console.log(error);
        return;
    }  
}

var theObject = await s3.getObject (params) .promise () 이것이 올바른 방법입니다. 감사합니다
유쾌한

0

콜백을 피하려면 다음과 같이 sdk .promise () 함수를 이용할 수 있습니다.

const s3 = new AWS.S3();
const params = {Bucket: 'myBucket', Key: 'myKey.csv'}
const response = await s3.getObject(params).promise() // await the promise
const fileContent = getObjectResult.Body.toString('utf-8'); // can also do 'base64' here if desired

여기에 언급 된 다른 방법에도 장점이 있지만이 방법은 저에게 효과적입니다. 이 스레드에서 출처 (AWS의 마지막 응답 참조) : https://forums.aws.amazon.com/thread.jspa?threadID=116788


1
마지막 줄에서 getObjectResult는 무엇입니까?
Felipe Deveza

0
var fileStream = fs.createWriteStream('/path/to/file.jpg');
var s3Stream = s3.getObject({Bucket: 'myBucket', Key: 'myImageFile.jpg'}).createReadStream();

// Listen for errors returned by the service
s3Stream.on('error', function(err) {
    // NoSuchKey: The specified key does not exist
    console.error(err);
});

s3Stream.pipe(fileStream).on('error', function(err) {
    // capture any errors that occur when writing data to the file
    console.error('File Stream:', err);
}).on('close', function() {
    console.log('Done.');
});

참조 : https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/requests-using-stream-objects.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.