使用 aws-sdk 将 gm 调整大小的图像流上传到 s3
Posted
技术标签:
【中文标题】使用 aws-sdk 将 gm 调整大小的图像流上传到 s3【英文标题】:stream uploading an gm-resized image to s3 with aws-sdk 【发布时间】:2013-03-26 21:55:12 【问题描述】:所以我想做的是从 url 流式传输图像,使用 graphicsmagick 处理它并将其流式上传到 s3。我只是不让它工作。
将处理后的图像流式传输到本地磁盘(使用 fs.createWriteStream)没有问题。
当我缓冲我的流时,s3 中的最终图像至少具有预期的大小(kb-wise),但我无法打开该图像。
这是我目前的进度:
var request = require('request');
var gm = require("gm");
var AWS = require('aws-sdk');
var mime = require('mime');
var s3 = new AWS.S3();
gm(request('http://www.some-domain.com/some-image.jpg'), "my-image.jpg")
.resize("100^", "100^")
.stream(function(err, stdout, stderr)
var str = '';
stdout.on('data', function(data)
str += data;
);
stdout.on('end', function(data)
var data =
Bucket: "my-bucket",
Key: "my-image.jpg",
Body: new Buffer(str, 'binary'), // thats where im probably wrong
ContentType: mime.lookup("my-image.jpg")
;
s3.client.putObject(data, function(err, res)
console.log("done");
);
);
);
我确实尝试了一些东西,比如创建文件写入流和文件读取流,但我认为应该有一些更干净更好的解决方案来解决这个问题......
编辑:我尝试的第一件事是将 Body 设置为标准输出(@AndyD 的建议答案):
var data =
Bucket: "my-bucket",
Key: "my-image.jpg",
Body: stdout,
ContentType: mime.lookup("my-image.jpg")
;
但返回以下错误:
Cannot determine length of [object Object]'
EDIT2:
nodeversion:0.8.6(我也试过0.8.22和0.10.0) aws-sdk:0.9.7-pre.8(今天安装)完整的错误:
[Error: Cannot determine length of [object Object]]
message: 'Cannot determine length of [object Object]',
object:
_handle:
writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread] ,
_pendingWriteReqs: 0,
_flags: 0,
_connectQueueSize: 0,
destroyed: false,
errorEmitted: false,
bytesRead: 0,
_bytesDispatched: 0,
allowHalfOpen: undefined,
writable: false,
readable: true,
_paused: false,
_events: close: [Function], error: [Function: handlerr] ,
name: 'Error'
【问题讨论】:
【参考方案1】:您不需要自己读取流(在您的情况下,您似乎正在从二进制转换为字符串并返回,因为 var str='' 然后附加作为二进制缓冲区等的数据......
尝试让 putObject 像这样对流进行管道传输:
gm(request('http://www.some-domain.com/some-image.jpg'), "my-image.jpg")
.resize("100^", "100^")
.stream(function(err, stdout, stderr)
var data =
Bucket: "my-bucket",
Key: "my-image.jpg",
Body: stdout
ContentType: mime.lookup("my-image.jpg")
;
s3.client.putObject(data, function(err, res)
console.log("done");
);
);
);
查看这些release notes 了解更多信息。
如果流/管道不起作用,那么类似这样的东西可能会将所有内容加载到内存中然后上传。在这种情况下,我认为你被限制为 4Mb。
var buf = new Buffer('');
stdout.on('data', function(data)
buf = Buffer.concat([buf, data]);
);
stdout.on('end', function(data)
var data =
Bucket: "my-bucket",
Key: "my-image.jpg",
Body: buf,
ContentType: mime.lookup("my-image.jpg")
;
s3.client.putObject(data, function(err, res)
console.log("done");
);
);
【讨论】:
这是我尝试的第一件事,因为标准输出应该已经是一个流,对吧?但这不起作用,最后一个回调中的“错误”说“无法确定 [object Object] 的长度”;-( 你有堆栈跟踪吗?您使用的是最新版本的 aws-SDK 吗? 不,这就是我得到的全部。我认为 aws-sdk 有问题,我在他们的 github 页面上打开了一个:github.com/aws/aws-sdk-js/issues/94 您的缓冲区示例有效(当您使用空字符串 'new Buffer("")' 实例化缓冲区时)。我会接受并赞成您的回答,因为这有助于解决我最初的问题。当然我更喜欢真正的流媒体解决方案,但我认为这是一个 aws-sdk 问题。非常感谢! 谢谢。您也可以使用 knox + knox-mpu(分段上传)模块进行流式传输,但我现在更喜欢官方 sdk。以上是关于使用 aws-sdk 将 gm 调整大小的图像流上传到 s3的主要内容,如果未能解决你的问题,请参考以下文章