【问题标题】:Pushing binary data to Amazon S3 using Node.js使用 Node.js 将二进制数据推送到 Amazon S3
【发布时间】:2013-10-01 16:57:51
【问题描述】:

我正在尝试使用 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 请求并填充“文件”字段。该文件最终位于 API 端,它可能位于某个 tmp 目录中。 Amazon 的 S3 putObject 方法需要 Stream,因此您需要通过为“fs”模块提供上传文件所在的路径来创建读取流。

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

【问题讨论】:

    标签: node.js amazon-s3 binary buffer


    【解决方案1】:

    我认为您需要在标头中传递内容长度,如 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;
        });
    
    });
    

    更新

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

    如果您需要/想要流式传输更棘手的文件,虽然当然可能,并且如果您不处理图像,您可能希望考虑采用 CORS 方法并直接上传到 S3,如下所述:@987654323 @

    【讨论】:

    • 我在 Node.js 上收到二进制文件,这意味着我没有图像路径,如果我将图像放在我的计算机上的目录中的话。这是否意味着我不能使用 fs 库,因为它处理文件系统?
    • 您是使用 express 还是 connect(两者都使用强大的文件上传解析)来处理 'localhost:3031/upload/image'?
    • 我正在使用 express 来处理 'localhost:3031/upload/image'。然后我可以通过查看 req.body(请求的正文)来访问上传的文件。当然,这是一个混乱。不知道如何将它变成 Amazon S3 的 pushObject 想要的 Buffer。
    • 那么您根本不需要将其转换为缓冲区,您只需使用fs.stat(req.body) 获取文件大小,然后使用fs.createReadStream(req.body) 创建一个流,然后将其传递给 S3作为Body 参数
    • fs.stat(req.body) 抱怨它需要一个字符串(req.body 是二进制数据,它不是字符串)。如果我将二进制 .jpg 转换为字符串,我以后将无法使用 Web 浏览器访问它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    相关资源
    最近更新 更多