Node.js'de S3 getObject'ten nasıl yanıt alınır?


90

Bir Node.js projesinde, verileri S3'ten geri almaya çalışıyorum.

Kullandığımda getSignedURLher şey çalışıyor:

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

Parametrelerim:

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

URL çıktısını konsola alıp bir web tarayıcısına yapıştırırsam, ihtiyacım olan dosyayı indirir.

Bununla birlikte, kullanmaya çalışırsam getObjecther türlü tuhaf davranışla karşılaşırım. Sadece yanlış kullandığıma inanıyorum. Bu denediğim şey:

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

Çıktılar:

{ 
  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

Yani bu düzgün çalışıyor gibi görünüyor. Ancak, e'lerden birine bir kesme noktası koyduğumda console.log, IDE'm (NetBeans) bir hata atıyor ve verilerin değerini göstermeyi reddediyor. Bu sadece IDE olabilirken, kullanmanın başka yollarını denemeye karar verdim getObject.

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

Bu hiçbir çıktı vermez. Bir kesme noktası koymak, kodun hiçbir zaman URL'lere ulaşmadığını gösterir console.log. Ben de denedim:

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

Ancak, bu aynı zamanda herhangi bir çıktı vermez ve bir kesme noktası yerleştirmek console.log, hiçbir zaman ulaşılmadığını gösterir.

Neyi yanlış yapıyorum?


Sizin mi awsaslında nesne yeni bir örneğini aws.S3nesne? Ayrıca, yanıt getObject()bir http yanıtına geri mi aktarılıyor yoksa bir dosyaya mı aktarılıyor?
peteb

@peteb aws = new AWS.S3(). Yanıt bir dosyaya aktarılmamalıdır. Bunu Javascript'te kullanmam gerekiyor
Sara Tibbetts

Öyleyse, içeriğin JSON veya XML olduğunu varsaymak güvenli midir?
peteb

@peteb ne de özel bir dosya formatı
Sara Tibbetts

Aramada kullandığınız parametreleri gösterin getObject(). GetObject için imzalanmış bir URL göndermeye çalışıyorsanız, bunun işe yarayacağını sanmıyorum.
Mark B

Yanıtlar:


177

getObject()S3 API'den bir işlem yaparken , dokümanlara göre dosyanızın içeriği, Bodyörnek çıktınızdan görebileceğiniz mülkte bulunur . Aşağıdakine benzer bir koda sahip olmalısınız

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

Nesneden yeni bir tampon oluşturmanıza gerek olmayabilir, ancak ihtiyacınız data.Bodyolursa bunu elde etmek için yukarıdaki örneği kullanabilirsiniz.


Yani geri gelen veriler Bufferaşina olmadığım bir nesne gibi görünüyor . Teorik new Buffer(data.Body).toString('utf-8');olarak içeriğe ulaşmak için kullanabilir miyim ?
Sara Tibbetts

4
İçerik zaten bir Tampon ise, bundan yeni bir Tampon oluşturmanıza gerek yoktur. Sadece yap data.Body.toString('utf-8');. Bir Tampon, düğümdeki İkili verilerin temsilidir, daha fazla bilgiye ihtiyacınız varsa işte belgeler
peteb

4
Bu, metin için işe yarar, ancak metin dosyalarının yanı sıra .png, .jpg, vb. İçin genel bir çözüm var mı?
carter

4
@carter Bu genel bir çözümdür. Görüntüler için ikili bir dize istiyorsanız , yalnızca .toString('utf8')erişirken değiştirin . Eğer içinde bu soruya gibi bir dize dönüştürülmesi gerekmez, o zaman sadece dönebilirsiniz ile ve çalışma direkt. data.Body.toString('binary')Bufferdata.Bodydata.BodyBuffer
peteb

1
AWS belgeleri bunu biraz daha açık hale getirseydi "Gövdeyi Bir Arabellekten Dizeye Dönüştür" ... harika olurdu. AWS ile güreşmekten bıktım usandım.
osullic

30

@Peteb'in cevabına göre, ancak Promisesve kullanarak 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 () 'in sonundaki .promise () benim için anahtardı. AWS SDK'yı zaman zaman biraz mantıksız buluyorum.
Andrew Harris


1
@jonask getObject()bir eşzamansız işlevdir, onunla aramayı denediniz await getObject(...)mi?
Arian Acosta

6

NEST JS TYPESCRIPTYukarıdakilerin bir sürümünü arayan biri için :

    /**
     * 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

Alternatif olarak minio-js istemci kitaplığını get-object.js kullanabilirsiniz.

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

Sorumluluk reddi: Minio için çalışıyorum Java , Python , Js , golang'da mevcut istemci kitaplıkları ile golang ile yazılmış açık kaynaklı, S3 uyumlu nesne depolaması .


Mino denedim, ancak dataStream.Body yazdırdığımda arabellek verisi nasıl alınır, 'tanımsız' veriyor. ie console.log ('datastream', dataStream.Body); // undefined
Dibish

3

İlk bakışta yanlış bir şey yapıyormuşsunuz gibi görünmüyor ancak tüm kodunuzu göstermiyorsunuz. Aşağıdakiler, S3 ve Node'u ilk kontrol ettiğimde benim için çalıştı:

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());
        });
    }
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.