S3 getObject से Node.js में प्रतिक्रिया कैसे प्राप्त करें?


90

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.logलगाता हूं, तो मेरी आईडीई (नेटबाइन्स) एक त्रुटि को फेंक देती है और डेटा के मूल्य को दिखाने से इनकार करती है। हालांकि यह सिर्फ आईडीई हो सकता है, मैंने उपयोग करने के अन्य तरीकों की कोशिश करने का फैसला किया getObject

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

यह कुछ भी आउटपुट नहीं करता है। एक ब्रेकपॉइंट लगाने से पता चलता है कि कोड कभी भी एस तक नहीं पहुंचता है console.log। मैंने भी कोशिश की:

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

हालांकि, यह भी कुछ भी आउटपुट नहीं करता है और ब्रेकपॉइंट रखने से पता चलता है कि console.logकभी नहीं पहुंचा गया है।

मैं क्या गलत कर रहा हूं?


क्या आपकी awsवस्तु वास्तव में वस्तु का एक नया उदाहरण है aws.S3? इसके अलावा, क्या प्रतिक्रिया getObject()एक http प्रतिक्रिया के लिए वापस पारित किया जा रहा है या यह एक फ़ाइल के लिए पाइप किया जा रहा है?
पेटिब

@ पेेटब aws = new AWS.S3()। प्रतिक्रिया को फ़ाइल में नहीं डाला जाना चाहिए। मुझे इसका उपयोग जावास्क्रिप्ट में करने की आवश्यकता है
सारा टिब्बेट्स

तो क्या यह मान लेना सुरक्षित है कि सामग्री JSON या XML है?
पेटे

@peteb न तो, वे एक कस्टम फ़ाइल स्वरूप हैं
सारा तिब्बत

getObject()कॉल में आपके द्वारा उपयोग किए जा रहे परमेस दिखाएं । यदि आप getObject के लिए एक हस्ताक्षरित URL पास करने की कोशिश कर रहे हैं तो मुझे नहीं लगता कि यह काम करेगा।
मार्क बी

जवाबों:


178

जब एक कर getObject(), एस 3 एपीआई से प्रति डॉक्स आपकी फ़ाइल की सामग्री में स्थित हैं 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');सामग्री प्राप्त करने के लिए उपयोग कर सकता हूं ?
सारा तिब्बत

4
यदि सामग्री पहले से ही बफ़र है, तो उससे एक नया बफ़र बनाने की आवश्यकता नहीं है। बस करो data.Body.toString('utf-8');। एक बफ़र नोड में द्विआधारी डेटा का प्रतिनिधित्व है, अगर आपको अधिक जानकारी की आवश्यकता है तो यहां डॉक्स हैं
पीटीबी

4
यह पाठ के लिए काम करता है, लेकिन क्या पाठ फ़ाइलों के साथ-साथ .png, .jpg, आदि को संभालने के लिए एक सामान्य समाधान है?
कार्टर

4
@ क्वार्टर यह एक सामान्य समाधान है। बस बदल .toString('utf8')जब तक पहुँचने data.Bodyके लिए .toString('binary')अगर आप छवियों के लिए एक बाइनरी स्ट्रिंग चाहते हैं। अगर Bufferमें data.Bodyइस सवाल में की तरह एक स्ट्रिंग के लिए परिवर्तित करने की आवश्यकता नहीं है, तो आप सिर्फ लौट सकते हैं data.Bodyऔर साथ काम Bufferसीधे।
पेट

1
"कन्वर्ट बॉडी फ्रॉम अ बफ़र टू अ स्ट्रींग" ... बहुत अच्छा होगा अगर AWS डॉक्स ने इसे थोड़ा और स्पष्ट कर दिया। मैं AWS से कुश्ती से काफी तंग आ रहा हूं।
ओशुलिक

30

@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
.Oromise () getObject के अंत पर () मेरे लिए महत्वपूर्ण था। मुझे कई बार AWS SDK का पता नहीं चला।
एंड्रयू हैरिस

मेरी प्रतिक्रिया कह रही है 'वादा {<लंबित>}'
जौनसक

1
@ जोंसक getObject()एक एसिंक्स फ़ंक्शन है, क्या आपने इसे कॉल करने का प्रयास किया था await getObject(...)?
एरियन अकोस्टा

6

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

अस्वीकरण: मैं मिनियो के लिए काम करता हूं इसका खुला स्रोत, एस 3 संगत ऑब्जेक्ट स्टोरेज जोलंग में जावा , पाइथन , जेएस , गोलंग में उपलब्ध क्लाइंट लाइब्रेरी के साथ लिखा गया है ।


कोशिश की मिनो, लेकिन कैसे मैं बफर डेटा प्राप्त करूं, जब मैं dataStream प्रिंट करता हूं। लेकिन इसके 'अपरिभाषित' देने पर। कंसोल.लॉग ('डेटास्ट्रीम', डेटास्ट्रीम.बॉडी); // अपरिभाषित
दिबिश

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());
        });
    }
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.