使用Node.js将二进制数据推送到Amazon S3

Jac*_*ack 13 binary buffer amazon-s3 node.js

我正在尝试拍摄图像并使用Node.js将其上传到Amazon S3存储桶.最后,我希望能够将图像推送到S3,然后能够访问该S3 URL并在浏览器中查看图像.我正在使用Curl查询来执行HTTP POST请求,并将图像作为正文.

curl -kvX POST --data-binary "@test.jpg" 'http://localhost:3031/upload/image'

然后在Node.js方面,我这样做:

exports.pushImage = function(req, res) {
    var image = new Buffer(req.body);
    var s3bucket = new AWS.S3();
    s3bucket.createBucket(function() {
        var params = {Bucket: 'My/bucket', Key: 'test.jpg', Body: image};
        // Put the object into the bucket.
        s3bucket.putObject(params, function(err) {
            if (err) {
                res.writeHead(403, {'Content-Type':'text/plain'});
                res.write("Error uploading data");
                res.end()
            } else {
                res.writeHead(200, {'Content-Type':'text/plain'});
                res.write("Success");
                res.end()
            }
        });
    });
};
Run Code Online (Sandbox Code Playgroud)

我的文件是0字节,如Amazon S3上所示.我该如何制作它以便我可以使用Node.js将二进制文件推送到S3?我对二进制数据和缓冲区做错了什么?

更新:

我发现了我需要做的事情.curl查询是应该更改的第一件事.这是工作的:

curl -kvX POST -F foobar=@my_image_name.jpg 'http://localhost:3031/upload/image'

然后,我添加了一行来转换为Stream.这是工作代码:

exports.pushImage = function(req, res) {
    var image = new Buffer(req.body);
    var s3bucket = new AWS.S3();
    s3bucket.createBucket(function() {
        var bodyStream = fs.createReadStream(req.files.foobar.path);
        var params = {Bucket: 'My/bucket', Key: 'test.jpg', Body: bodyStream};
        // Put the object into the bucket.
        s3bucket.putObject(params, function(err) {
            if (err) {
                res.writeHead(403, {'Content-Type':'text/plain'});
                res.write("Error uploading data");
                res.end()
            } else {
                res.writeHead(200, {'Content-Type':'text/plain'});
                res.write("Success");
                res.end()
            }
        });
    });
};
Run Code Online (Sandbox Code Playgroud)

因此,为了将文件上传到API端点(使用Node.js和Express)并让API将该文件推送到Amazon S3,首先需要执行POST请求并填充"files"字段.该文件最终在API端,它可能位于某个tmp目录中.亚马逊的S3 putObject方法需要一个Stream,因此您需要通过为'fs'模块提供上传文件所在的路径来创建读取流.

我不知道这是否是上传数据的正确方法,但它确实有效.有没有人知道是否有办法在请求体内发布二进制数据并让API将其发送给S3?我不太清楚多部分上传与标准POST到正文的区别.

dri*_*tiv 7

我相信您需要传递标题中的内容长度,如S3文档中所述:http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html

在花费大量时间将资产推送到S3后,我最终使用了AwsSum库,在生产中取得了优异的成果:

https://github.com/awssum/awssum-amazon-s3/

(请参阅有关设置AWS凭据的文档)

例:

var fs = require('fs');
var bucket_name = 'your-bucket name'; // AwsSum also has the API for this if you need to create the buckets

var img_path = 'path_to_file';
var filename = 'your_new_filename';

// using stat to get the size to set contentLength
fs.stat(img_path, function(err, file_info) {

    var bodyStream = fs.createReadStream( img_path );

    var params = {
        BucketName    : bucket_name,
        ObjectName    : filename,
        ContentLength : file_info.size,
        Body          : bodyStream
    };

    s3.putObject(params, function(err, data) {
        if(err) //handle
        var aws_url = 'https://s3.amazonaws.com/' + DEFAULT_BUCKET + '/' + filename;
    });

});
Run Code Online (Sandbox Code Playgroud)

UPDATE

因此,如果您使用的是基于Formidable构建的Express或Connect之类的东西,那么当Formidable将文件写入磁盘时,您无法访问文件流.因此,根据您在客户端上传的方式,图像将位于req.body或中req.files.在我的情况下,我使用Express,在客户端,我也发布其他数据,因此图像有自己的参数,并作为req.files.img_data.无论您访问它,该param都是您传入的内容,img_path如上例所示.

如果你需要/想涧是棘手的文件,但肯定可以,如果你不处理图像,你可能想看看在采取CORS方法,并直接上传到S3为这里讨论:流用户直接上传到亚马逊s3