W projekcie Node.js próbuję odzyskać dane z S3.
Kiedy używam getSignedURL
, wszystko działa:
aws.getSignedUrl('getObject', params, function(err, url){
console.log(url);
});
Moje parametry to:
var params = {
Bucket: "test-aws-imagery",
Key: "TILES/Level4/A3_B3_C2/A5_B67_C59_Tiles.par"
Jeśli wezmę wyjście URL do konsoli i wkleię je w przeglądarce internetowej, pobierze potrzebny plik.
Jednak jeśli próbuję użyć getObject
, otrzymuję różne dziwne zachowanie. Uważam, że po prostu używam go nieprawidłowo. Oto, czego próbowałem:
aws.getObject(params, function(err, data){
console.log(data);
console.log(err);
});
Wyjścia:
{
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
Wygląda więc na to, że to działa poprawnie. Jednak kiedy umieszczam punkt przerwania na jednym z console.log
s, moje IDE (NetBeans) zgłasza błąd i odmawia pokazania wartości danych. Chociaż może to być po prostu IDE, zdecydowałem się wypróbować inne sposoby użycia getObject
.
aws.getObject(params).on('httpData', function(chunk){
console.log(chunk);
}).on('httpDone', function(data){
console.log(data);
});
To nic nie daje. Umieszczenie punktu przerwania w pokazuje, że kod nigdy nie osiągnie żadnego z plików console.log
s. Próbowałem też:
aws.getObject(params).on('success', function(data){
console.log(data);
});
Jednak to również nic nie wyświetla, a umieszczenie punktu przerwania pokazuje, że console.log
nigdy nie został osiągnięty.
Co ja robię źle?
źródło
aws
obiekt jest rzeczywiście nową instancjąaws.S3
obiektu? Ponadto, czy odpowiedźgetObject()
jest przekazywana z powrotem do odpowiedzi http, czy też jest przesyłana potokiem do pliku?aws = new AWS.S3()
. Odpowiedź nie powinna być przesyłana potokiem do pliku. Muszę go użyć wgetObject()
rozmowie. Jeśli próbujesz przekazać podpisany adres URL do getObject, nie sądzę, że to zadziała.Odpowiedzi:
Podczas wykonywania
getObject()
z interfejsu API S3, zgodnie z dokumentacją zawartość pliku znajduje się weBody
właściwości, którą można zobaczyć w przykładowych danych wyjściowych. Powinieneś mieć kod, który wygląda mniej więcej takconst 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 });
Być może nie będziesz musiał tworzyć nowego bufora z
data.Body
obiektu, ale jeśli potrzebujesz, możesz użyć powyższego przykładu, aby to osiągnąć.źródło
Buffer
obiektem, którego nie znam. Teoretycznie mógłbym skorzystać,new Buffer(data.Body).toString('utf-8');
żeby dostać się do treści?data.Body.toString('utf-8');
. Bufor jest reprezentacją danych binarnych w węźle, jeśli potrzebujesz więcej informacji, tutaj znajdziesz dokumentację.toString('utf8')
podczas uzyskiwania dostępudata.Body
do.toString('binary')
jeżeli chcesz ciąg binarny dla obrazów. JeśliBuffer
indata.Body
nie musi być konwertowane na ciąg, jak w tym pytaniu, możesz po prostu wrócićdata.Body
i pracowaćBuffer
bezpośrednio z.Na podstawie odpowiedzi @peteb, ale przy użyciu
Promises
iAsync/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(...);
źródło
getObject()
to funkcja asynchroniczna, czy próbowałeś ją wywołaćawait getObject(...)
?Dla kogoś szukającego
NEST JS TYPESCRIPT
wersji powyższego:/** * 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); } }
źródło
Alternatywnie możesz użyć biblioteki klienta 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) }) })
Zastrzeżenie: pracuję dla Minio Jego open source, obiektowa pamięć masowa zgodna z S3 napisana w języku golang z bibliotekami klienta dostępnymi w językach Java , Python , Js , golang .
źródło
Na pierwszy rzut oka nie wygląda na to, że robisz coś złego, ale nie pokazujesz całego kodu. Poniższe działały dla mnie, kiedy po raz pierwszy sprawdzałem S3 i 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()); }); } });
źródło