使用适用于 Node.js 的 AWS 开发工具包将二进制文件上传到 S3

Posted

技术标签:

【中文标题】使用适用于 Node.js 的 AWS 开发工具包将二进制文件上传到 S3【英文标题】:Upload a binary file to S3 using AWS SDK for Node.js 【发布时间】:2012-11-28 05:50:37 【问题描述】:

更新:为了将来参考,亚马逊现在已经根据询问时的内容更新了文档。根据@Loren Segal 下面的评论:-

我们已更正最新预览版中的文档,以正确记录此参数。抱歉混淆了!


我正在试用 the AWS SDK for Node.Js 的开发者预览版,并希望使用 putObject 将压缩的 tarball 上传到 S3。

根据the documentation,Body参数应该是……

正文 -(Base64 编码数据)

...因此,我正在尝试以下代码...

var AWS = require('aws-sdk'),
    fs = require('fs');

// For dev purposes only
AWS.config.update( accessKeyId: 'key', secretAccessKey: 'secret' );

// Read in the file, convert it to base64, store to S3
fs.readFile('myarchive.tgz', function (err, data) 
  if (err)  throw err; 

  var base64data = new Buffer(data, 'binary').toString('base64');

  var s3 = new AWS.S3();
  s3.client.putObject(
    Bucket: 'mybucketname',
    Key: 'myarchive.tgz',
    Body: base64data
  ).done(function (resp) 
    console.log('Successfully uploaded package.');
  );

);

虽然我可以在 S3 中看到该文件,但如果我下载它并尝试解压缩它,我会收到文件已损坏的错误消息。因此,我的“base64 编码数据”方法似乎已关闭。

有人可以帮我使用putObject 上传二进制文件吗?

【问题讨论】:

【参考方案1】:

您不需要将缓冲区转换为 base64 字符串。只需将 body 设置为 data 即可。

【讨论】:

好像就是这样!不确定文档中提到“base64”的原因 我们已经更正了最新预览版中的文档以正确记录此参数。很抱歉混淆了! 是否可以传递一个 Stream 而不是 data ?例如,我想发送一个 50MB 的文件。我可以在内部将可读流和 S3.client 管道传递给 S3 吗? 是的,这是可能的。看这里:***.com/questions/15817746/…【参考方案2】:

这是一种使用流发送文件的方法,这对于大文件可能是必需的,并且通常会减少内存开销:

var AWS = require('aws-sdk'),
    fs = require('fs');

// For dev purposes only
AWS.config.update( accessKeyId: 'key', secretAccessKey: 'secret' );

// Read in the file, convert it to base64, store to S3
var fileStream = fs.createReadStream('myarchive.tgz');
fileStream.on('error', function (err) 
  if (err)  throw err; 
);  
fileStream.on('open', function () 
  var s3 = new AWS.S3();
  s3.putObject(
    Bucket: 'mybucketname',
    Key: 'myarchive.tgz',
    Body: fileStream
  , function (err) 
    if (err)  throw err; 
  );
);

【讨论】:

这不适用于 mp4 文件。上传的文件不等于来源。 我不知道你说的“上传的文件不等于原始文件”是什么意思。我使用与此类似的代码将二进制 MP4 文件上传到 AWS。听起来好像您正在尝试在浏览器而不是 NodeJS 中运行此代码?你能说得更具体点吗? 我也无法使用此方法上传 MP4 文件。该文件显示在 S3 存储桶中,但已损坏且无法播放。 嗯,我不确定你们为什么会遇到问题。我使用这样的代码上传 MP4 文件,我可以下载并再次播放。我不知道这有什么不同,但我不是“流式传输”文件。我完全下载并播放它们——但我认为这不会有任何区别。我使用 ubuntu 主机将文件发送到 S3。您可以在此处查看我在上面创建此示例的代码:github.com/CaptEmulation/soapbubble-cloud/blob/… 一个关键区别是此代码首先检查文件是否存在 看来您是正确的,这似乎是 Amazon S3 库中的一个实施问题。 S3 需要定期暂停流,以防止FileStream 继续从磁盘读取数据并放入内存。您可能能够创建一个适配器流实现来跟踪读取但未发送的总字节数并自行暂停。我没有看到任何简单的参数可以通过胶水实现来解决这个问题。【参考方案3】:

我可以通过这种方式上传我的二进制文件。

var fileStream = fs.createReadStream("F:/directory/fileName.ext");
var putParams = 
    Bucket: s3bucket,
    Key: s3key,
    Body: fileStream
;
s3.putObject(putParams, function(putErr, putData)
    if(putErr)
        console.error(putErr);
     else 
        console.log(putData);
    
);

【讨论】:

以上是关于使用适用于 Node.js 的 AWS 开发工具包将二进制文件上传到 S3的主要内容,如果未能解决你的问题,请参考以下文章

如何使用适用于 Node.js 的 AWS 开发工具包将 Amazon S3 中的所有对象从一个前缀复制/移动到另一个前缀

为啥我在 s3 上的访问被拒绝(使用适用于 Node.js 的 aws-sdk)?

使用适用于 Ruby 的 AWS 开发工具包发布到 SNS 主题时指定区域

如何包含适用于 Node.js 的 Amazon EC2 库?

使用适用于 Ruby 的 AWS 开发工具包时在 AWS Kinesis Firehose 记录之间插入换行符

从适用于 PHP 的 AWS 开发工具包中提取受保护的请求响应