在 node 中.js项目我正在try 从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输出带到控制台并将其粘贴到web浏览器中,它会下载我需要的文件.

然而,如果我try 使用getObject,我会有各种奇怪的行为.我想我只是用错了.这就是我try 过的:

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上设置断点时,我的IDE(NetBeans)抛出一个错误并拒绝显示数据的值.虽然这可能只是IDE,但我决定try 其他方法来使用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.

我做错了什么?

推荐答案

从S3API执行getObject()时,根据docs,文件的内容位于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对象创建新的缓冲区,但如果需要,可以使用上面的示例来实现这一点.

@ AWS SDK/Cclipse S3(2021更新)

自从我在2016年写下这个答案以来,亚马逊发布了一个新的JavaScript SDK,@aws-sdk/client-s3.这个新版本改进了原来的getObject(),它总是返回一个promise ,而不是 Select 通过.promise()链接到getObject().除此之外,response.Body不再是Buffer,而是Readable|ReadableStream|Blob中的一个.这会稍微改变response.Data的处理方式.这应该更具性能,因为我们可以对返回的数据进行流式处理,而不是将所有内容都保存在内存中,这样做的代价是,实现起来会更加冗长.

在下面的示例中,response.Body个数据将被流式传输到一个数组中,然后作为字符串返回.这是与我最初的答案相同的例子.或者,response.Body可以使用stream.Readable.pipe()来发送HTTP响应、文件或任何其他类型的stream.Writeable以供进一步使用,这将是获取大型对象时性能更高的方式.

如果你想使用Buffer,就像最初的getObject()响应一样,这可以通过将responseDataChunks包装在Buffer.concat()中而不是使用Array#join()来实现,这在与二进制数据交互时会很有用.注意,由于Array#join()返回一个字符串,responseDataChunks中的每个Buffer实例将隐式调用Buffer.toString(),并将使用默认编码utf8.

const { GetObjectCommand, S3Client } = require('@aws-sdk/client-s3')
const client = new S3Client() // Pass in opts to S3 if necessary

function getObject (Bucket, Key) {
  return new Promise(async (resolve, reject) => {
    const getObjectCommand = new GetObjectCommand({ Bucket, Key })

    try {
      const response = await client.send(getObjectCommand)
  
      // Store all of data chunks returned from the response data stream 
      // into an array then use Array#join() to use the returned contents as a String
      let responseDataChunks = []

      // Handle an error while streaming the response body
      response.Body.once('error', err => reject(err))
  
      // Attach a 'data' listener to add the chunks of data to our array
      // Each chunk is a Buffer instance
      response.Body.on('data', chunk => responseDataChunks.push(chunk))
  
      // Once the stream has no more data, join the chunks into a string and return the string
      response.Body.once('end', () => resolve(responseDataChunks.join('')))
    } catch (err) {
      // Handle the error or throw
      return reject(err)
    } 
  })
}

@aws-sdk/client-s3 Documentation Links

Node.js相关问答推荐

使用OpenAI API时遇到问题

如何在Firebase Cloud Function v2计划函数中设置代码中的时区?

MongoDB-$Lookup未获得适当的结果

如何从shell脚本中计算ecmascript模块?

使用AWS SDK for JavaScript V3将图像从node.js上传到s3 bucket

如何在nodejs中打印pdf

Mongodb - 在数组数组中查找()

与诗乃一起嘲笑奈克斯

使用 fs.createWriteStream 将数据写入 bigquery (node.js) 时出现模式错误

处理 UTC 日期和future

为什么 req.params.id 返回 undefined未定义?

什么是nestjs错误处理方式(业务逻辑错误vs.http错误)?

如果我使用像 express 这样的 node 服务器,是否需要 webpack-dev-server

适用于 Windows 7 的 NodeJS

如何在 node 调试器中禁用第一行中断

Node.js 服务器中没有缓存

如何使用 Node.js 在服务器端管理多个 JS 文件

代理(如提琴手)可以与 Node.js 的 ClientRequest 一起使用吗

如何从 Node.js 中的 URL 获取

node.js 找不到模块mongodb