Em um projeto Node.js, estou tentando obter dados de S3.
Quando eu uso getSignedURL
, tudo funciona:
aws.getSignedUrl('getObject', params, function(err, url){
console.log(url);
});
Meus parâmetros são:
var params = {
Bucket: "test-aws-imagery",
Key: "TILES/Level4/A3_B3_C2/A5_B67_C59_Tiles.par"
Se eu pegar a saída do URL para o console e colá-la em um navegador da web, ele baixa o arquivo de que preciso.
No entanto, se tento usar getObject
, recebo todos os tipos de comportamento estranho. Eu acredito que estou apenas usando incorretamente. Isso é o que eu tentei:
aws.getObject(params, function(err, data){
console.log(data);
console.log(err);
});
Saídas:
{
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
Portanto, parece que isso está funcionando corretamente. No entanto, quando coloco um ponto de interrupção em um dos console.log
s, meu IDE (NetBeans) lança um erro e se recusa a mostrar o valor dos dados. Embora esse possa ser apenas o IDE, decidi tentar outras maneiras de usar getObject
.
aws.getObject(params).on('httpData', function(chunk){
console.log(chunk);
}).on('httpDone', function(data){
console.log(data);
});
Isso não produz nada. Colocar um ponto de interrupção em mostra que o código nunca atinge nenhum dos console.log
s. Eu também tentei:
aws.getObject(params).on('success', function(data){
console.log(data);
});
No entanto, isso também não produz nada e colocar um ponto de interrupção mostra que console.log
nunca foi alcançado.
O que estou fazendo errado?
fonte
aws
objeto é realmente uma nova instância doaws.S3
objeto? Além disso, a respostagetObject()
está sendo passada de volta para uma resposta http ou está sendo canalizada para um arquivo?aws = new AWS.S3()
. A resposta não deve ser canalizada para um arquivo. Preciso usá-lo no JavascriptgetObject()
chamada. Se você está tentando passar um URL assinado para getObject, não acho que funcione.Respostas:
Ao fazer um a
getObject()
partir da API S3, de acordo com os documentos, o conteúdo do seu arquivo está localizado naBody
propriedade, que você pode ver na sua saída de amostra. Você deve ter um código parecido com o seguinteconst 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 });
Você pode não precisar criar um novo buffer a partir do
data.Body
objeto, mas se precisar, pode usar o exemplo acima para fazer isso.fonte
Buffer
objeto, com o qual não estou familiarizado. Teoricamente, eu poderia usarnew Buffer(data.Body).toString('utf-8');
para chegar ao conteúdo?data.Body.toString('utf-8');
. Um Buffer é uma representação de dados binários no nó, se você precisar de mais informações aqui estão os documentos.toString('utf8')
ao acessardata.Body
para.toString('binary')
se você quer uma cadeia binária para imagens. Se oBuffer
indata.Body
não precisa ser convertido em uma String como nesta pergunta, você pode simplesmente retornardata.Body
e trabalhar com oBuffer
diretamente.Com base na resposta de @peteb, mas usando
Promises
eAsync/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(...);
fonte
getObject()
é uma função assíncrona, você tentou chamá-la comawait getObject(...)
?Para quem procura uma
NEST JS TYPESCRIPT
versão do acima:/** * 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); } }
fonte
Como alternativa, você pode usar a biblioteca cliente 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) }) })
Aviso de isenção de responsabilidade: Eu trabalho para o Minio Seu código aberto, armazenamento de objetos compatível com S3 escrito em golang com bibliotecas de cliente disponíveis em Java , Python , Js , golang .
fonte
À primeira vista, não parece que você está fazendo nada de errado, mas você não mostra todo o seu código. O seguinte funcionou para mim quando eu estava conferindo o S3 e o Node pela primeira vez:
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()); }); } });
fonte