Node.js의 S3 getObject에서 응답을 얻는 방법은 무엇입니까?


87

Node.js 프로젝트에서 S3에서 데이터를 가져 오려고합니다.

을 사용 getSignedURL하면 모든 것이 작동합니다.

aws.getSignedUrl('getObject', params, function(err, url){
    console.log(url); 
}); 

내 매개 변수는 다음과 같습니다.

var params = {
              Bucket: "test-aws-imagery", 
              Key: "TILES/Level4/A3_B3_C2/A5_B67_C59_Tiles.par"

URL 출력을 콘솔로 가져 와서 웹 브라우저에 붙여 넣으면 필요한 파일이 다운로드됩니다.

그러나 사용하려고 getObject하면 모든 종류의 이상한 행동이 나타납니다. 나는 그것을 잘못 사용하고 있다고 생각합니다. 이것이 내가 시도한 것입니다.

aws.getObject(params, function(err, data){
    console.log(data); 
    console.log(err); 
}); 

출력 :

{ 
  AcceptRanges: 'bytes',
  LastModified: 'Wed, 06 Apr 2016 20:04:02 GMT',
  ContentLength: '1602862',
  ETag: '9826l1e5725fbd52l88ge3f5v0c123a4"',
  ContentType: 'application/octet-stream',
  Metadata: {},
  Body: <Buffer 01 00 00 00  ... > }

  null

그래서 이것이 제대로 작동하는 것 같습니다. 그러나 console.logs 중 하나에 중단 점을 설정하면 IDE (NetBeans)에서 오류가 발생하고 데이터 값 표시를 거부합니다. 이것이 단지 IDE 일 수 있지만 .NET을 사용하는 다른 방법을 시도하기로 결정했습니다 getObject.

aws.getObject(params).on('httpData', function(chunk){
    console.log(chunk); 
}).on('httpDone', function(data){
    console.log(data); 
});

이것은 아무것도 출력하지 않습니다. 중단 점을 넣으면 코드가 console.logs에 도달하지 않음을 보여줍니다 . 나는 또한 시도했다 :

aws.getObject(params).on('success', function(data){
    console.log(data); 
});

그러나 이것은 또한 아무것도 출력하지 않으며 중단 점을 배치하면에 console.log도달하지 않음을 보여줍니다 .

내가 도대체 ​​뭘 잘못하고있는 겁니까?


귀하가 aws실제로 객체의 새로운 인스턴스 aws.S3객체? 또한 응답 getObject()이 http 응답으로 다시 전달되는 것입니까 아니면 파일로 파이프되고 있습니까?
peteb

@peteb aws = new AWS.S3(). 응답은 파일로 파이프되지 않아야합니다. Javascript에서 사용해야합니다
Sara Tibbetts

그렇다면 내용이 JSON 또는 XML이라고 가정하는 것이 안전합니까?
peteb apr

@peteb도, 그들은 사용자 정의 파일 형식입니다
사라 Tibbetts

getObject()통화 에서 사용중인 매개 변수를 표시합니다 . 서명 된 URL을 getObject에 전달하려는 경우 작동하지 않을 것이라고 생각합니다.
Mark B

답변:


172

getObject()S3 API에서를 수행하는 경우 문서 별로 파일의 내용이 Body속성에 있으며 샘플 출력에서 ​​볼 수 있습니다. 다음과 같은 코드가 있어야합니다.

const aws = require('aws-sdk');
const s3 = new aws.S3(); // Pass in opts to S3 if necessary

var getParams = {
    Bucket: 'abc', // your bucket name,
    Key: 'abc.txt' // path to the object you're looking for
}

s3.getObject(getParams, function(err, data) {
    // Handle any error and exit
    if (err)
        return err;

  // No error happened
  // Convert Body from a Buffer to a String

  let objectData = data.Body.toString('utf-8'); // Use the encoding necessary
});

data.Body객체 에서 새 버퍼를 만들 필요는 없지만 필요한 경우 위의 샘플을 사용하여이를 수행 할 수 있습니다.


그래서 되돌아 오는 데이터는 Buffer제가 익숙하지 않은 객체 인 것 같습니다 . 이론적으로 new Buffer(data.Body).toString('utf-8');콘텐츠에 액세스 하는 데 사용할 수 있습니까?
Sara Tibbetts

4
콘텐츠가 이미 버퍼 인 경우 여기에서 새 버퍼를 만들 필요가 없습니다. 그냥하세요 data.Body.toString('utf-8');. 버퍼는 노드의 바이너리 데이터를 표현한 것입니다. 더 많은 정보가 필요한 경우 여기 문서가 있습니다
peteb

4
이것은 텍스트에 대해 작동하지만 텍스트 파일과 .png, .jpg 등을 처리하는 일반적인 솔루션이 있습니까?
carter

4
@carter 이것은 일반적인 해결책입니다. 이미지에 대한 이진 문자열을 원하는 .toString('utf8')경우 액세스 data.Body할 때를 변경하십시오 .toString('binary'). 경우 Buffer에는 data.Body이 질문에 같은 문자열로 변환 할 필요가 없습니다, 당신은 반환 할 수 data.Body와 함께 작업 Buffer을 직접.
peteb

1
"Convert Body from a Buffer to a String"...은 AWS 문서가 이것을 좀 더 명확하게 만들었다면 좋을 것입니다. AWS와 씨름하는 데 꽤 지쳐 있습니다.
osullic

29

@peteb의 답변을 기반으로하지만 Promises및 사용 Async/Await:

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

const s3 = new AWS.S3();

async function getObject (bucket, objectKey) {
  try {
    const params = {
      Bucket: bucket,
      Key: objectKey 
    }

    const data = await s3.getObject(params).promise();

    return data.Body.toString('utf-8');
  } catch (e) {
    throw new Error(`Could not retrieve file from S3: ${e.message}`)
  }
}

// To retrieve you need to use `await getObject()` or `getObject().then()`
getObject('my-bucket', 'path/to/the/object.txt').then(...);

5
getObject () 끝에있는 .promise ()가 저에게 핵심이었습니다. 때때로 AWS SDK는 약간 직관적이지 않습니다.
Andrew Harris

내 응답은 'Promise {<pending>}'입니다
jonask

1
@jonask getObject()는 비동기 함수입니다 await getObject(...).
Arian Acosta

5

NEST JS TYPESCRIPT위 의 버전을 찾는 사람 :

    /**
     * to fetch a signed URL of a file
     * @param key key of the file to be fetched
     * @param bucket name of the bucket containing the file
     */
    public getFileUrl(key: string, bucket?: string): Promise<string> {
        var scopeBucket: string = bucket ? bucket : this.defaultBucket;
        var params: any = {
            Bucket: scopeBucket,
            Key: key,
            Expires: signatureTimeout  // const value: 30
        };
        return this.account.getSignedUrlPromise(getSignedUrlObject, params);
    }

    /**
     * to get the downloadable file buffer of the file
     * @param key key of the file to be fetched
     * @param bucket name of the bucket containing the file
     */
    public async getFileBuffer(key: string, bucket?: string): Promise<Buffer> {
        var scopeBucket: string = bucket ? bucket : this.defaultBucket;
        var params: GetObjectRequest = {
            Bucket: scopeBucket,
            Key: key
        };
        var fileObject: GetObjectOutput = await this.account.getObject(params).promise();
        return Buffer.from(fileObject.Body.toString());
    }

    /**
     * to upload a file stream onto AWS S3
     * @param stream file buffer to be uploaded
     * @param key key of the file to be uploaded
     * @param bucket name of the bucket 
     */
    public async saveFile(file: Buffer, key: string, bucket?: string): Promise<any> {
        var scopeBucket: string = bucket ? bucket : this.defaultBucket;
        var params: any = {
            Body: file,
            Bucket: scopeBucket,
            Key: key,
            ACL: 'private'
        };
        var uploaded: any = await this.account.upload(params).promise();
        if (uploaded && uploaded.Location && uploaded.Bucket === scopeBucket && uploaded.Key === key)
            return uploaded;
        else {
            throw new HttpException("Error occurred while uploading a file stream", HttpStatus.BAD_REQUEST);
        }
    }

4

또는 minio-js 클라이언트 라이브러리 get-object.js를 사용할 수 있습니다.

var Minio = require('minio')

var s3Client = new Minio({
  endPoint: 's3.amazonaws.com',
  accessKey: 'YOUR-ACCESSKEYID',
  secretKey: 'YOUR-SECRETACCESSKEY'
})

var size = 0
// Get a full object.
s3Client.getObject('my-bucketname', 'my-objectname', function(e, dataStream) {
  if (e) {
    return console.log(e)
  }
  dataStream.on('data', function(chunk) {
    size += chunk.length
  })
  dataStream.on('end', function() {
    console.log("End. Total size = " + size)
  })
  dataStream.on('error', function(e) {
    console.log(e)
  })
})

면책 조항 : 저는 Minio 에서 일하고 있습니다. Java , Python , Js , golang 에서 사용 가능한 클라이언트 라이브러리와 함께 golang으로 작성된 오픈 소스, S3 호환 객체 스토리지입니다 .


mino를 시도했지만 dataStream.Body를 인쇄 할 때 버퍼 데이터를 얻는 방법은 '정의되지 않음'을 제공합니다. 즉, console.log ( 'datastream', dataStream.Body); // undefined
Dibish

3

언뜻보기에 당신이 잘못한 것처럼 보이지는 않지만 모든 코드를 보여주지는 않습니다. 다음은 S3 및 Node를 처음 체크 아웃 할 때 저에게 효과적이었습니다.

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

if (typeof process.env.API_KEY == 'undefined') {
    var config = require('./config.json');
    for (var key in config) {
        if (config.hasOwnProperty(key)) process.env[key] = config[key];
    }
}

var s3 = new AWS.S3({accessKeyId: process.env.AWS_ID, secretAccessKey:process.env.AWS_KEY});
var objectPath = process.env.AWS_S3_FOLDER +'/test.xml';
s3.putObject({
    Bucket: process.env.AWS_S3_BUCKET, 
    Key: objectPath,
    Body: "<rss><data>hello Fred</data></rss>",
    ACL:'public-read'
}, function(err, data){
    if (err) console.log(err, err.stack); // an error occurred
    else {
        console.log(data);           // successful response
        s3.getObject({
            Bucket: process.env.AWS_S3_BUCKET, 
            Key: objectPath
        }, function(err, data){
            console.log(data.Body.toString());
        });
    }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.