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

标签 node.js amazon-s3 binary buffer

我正在尝试使用 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()
            }
        });
    });
};

我的文件是 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()
            }
        });
    });
};

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

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

最佳答案

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

在花费大量时间将 Assets 推送到 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;
    });

});

更新

因此,如果您使用的是基于 Formidable 构建的 Express 或 Connect,那么您无法访问文件流,因为 Formidable 会将文件写入磁盘。因此,根据您在客户端上传的方式,图像将位于 req.bodyreq.files 中。在我的例子中,我使用 Express,在客户端,我也发布了其他数据,因此图像有它自己的参数,并作为 req.files.img_data 访问。无论您如何访问它,该参数都是您在上述示例中作为 img_path 传入的参数。

如果您需要/想要流式传输更棘手的文件,但肯定有可能,并且如果您不处理图像,您可能需要考虑采用 CORS 方法并直接上传到 S3,如下所述:Stream that user uploads directly to Amazon s3

关于node.js - 使用 Node.js 将二进制数据推送到 Amazon S3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19016130/

相关文章:

json - 读取由 Amazon Kinesis Firehose 流写入 s3 的数据

c# - 为特定区域创建 S3 存储桶

node.js - 基于第一方express的 Node API的授权策略

node.js - 尝试通过 Firebase Cloud Functions (Android) 发送通知后出错

rest - 如何在 Amazon S3 上传后触发 REST 调用

websocket - 如何将Vec <u8>转换为bson::document::Document?

c - 如何使用C在char中存储8位

python - 在 Python 中保存 1 位深的二进制图像

node.js - NodeJS Passport session 序列化 - 将用户反序列化到 session 中?

javascript - 您可以提供另一个名称的模块吗?