web-dev-qa-db-fra.com

Comment obtenir une réponse de S3 getObject dans Node.js?

Dans un projet Node.js, je tente de récupérer les données de S3.

Quand j'utilise getSignedURL, tout fonctionne:

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

Mes params sont:

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

Si je prends l'URL vers la console et le colle dans un navigateur Web, il télécharge le fichier dont j'ai besoin.

Cependant, si j'essaie d'utiliser getObject j'obtiens toutes sortes de comportements étranges. Je crois que je ne l'utilise tout simplement pas correctement. C'est ce que j'ai essayé:

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

Les sorties:

{ 
  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

Il semble donc que cela fonctionne correctement. Cependant, lorsque je mets un point d'arrêt sur l'un des console.logs, mon IDE (NetBeans) renvoie une erreur et refuse d'afficher la valeur des données. Bien que cela puisse être juste l'IDE, j'ai décidé d'essayer d'autres manières d'utiliser getObject.

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

Cela ne produit rien. Mettre un point d'arrêt indique que le code n'atteint jamais aucun des console.logs. J'ai aussi essayé:

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

Cependant, cela ne génère rien et placer un point d'arrêt indique que le console.log n'est jamais atteint.

Qu'est-ce que je fais mal?

57
Sara Tibbetts

Lorsque vous exécutez une getObject() à partir de l'API S3, conformément à la docs , le contenu de votre fichier se trouve dans la propriété Body que vous pouvez voir à partir de votre exemple de sortie. Vous devriez avoir un code qui ressemble à ce qui suit

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

Vous n’avez peut-être pas besoin de créer un nouveau tampon à partir de l’objet data.Body, mais si vous en avez besoin, vous pouvez utiliser l’exemple ci-dessus pour y parvenir.

109
peteb

Basé sur la réponse de @peteb, mais en utilisant Promises et 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(...);
16
Arian Acosta

Vous pouvez aussi utiliser bibliothèque client 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)
  })
})

Disclaimer: Je travaille pour Minio Son open source, stockage d'objets compatibles S3 écrit en golang avec les bibliothèques client disponibles en Java , Python , Js , golang .

2
koolhead17

À première vue, il ne semble pas que vous fassiez quelque chose de mal, mais vous ne montrez pas tout votre code. Ce qui suit a fonctionné pour moi lorsque je vérifiais pour la première fois S3 et 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());
        });
    }
});
1
bknights