我在使用imagemagick处理图像时遇到问题,然后将其上传到S3。生成的对象具有不同(更大)的大小,似乎已损坏。如果我做一个中间步骤并首先将输出保存到本地tmp文件并将其读回,然后上传结果一切似乎都很好。这个代码不起作用。
im.resize({
srcData: imageObject.Body,
width: variant.width,
height: variant.height,
customArgs: ['-auto-orient']
}, function(err, stdout, stderr) {
if (err) {
// This resize completed successfully
log.err('Failed calling imageMagick, bail out', err);
callback(err);
return;
}
var fileName = cfg.aws.s3.uploadDir +
photo.imageId + '/' +
variant.width + 'x' + variant.height + '.jpg';
log.info('Storing image at S3 ' + fileName);
//fs.writeFileSync('/tmp/xxx.jpg', stdout, 'binary');
//stdout = fs.readFileSync('/tmp/xxx.jpg');
var x = new Buffer(stdout);
console.log(x);
s3.putObject(
{
Bucket: cfg.aws.s3.bucket,
Key: fileName,
Body: x,
ContentType: 'image/jpeg',
ACL: 'public-read'
},
function(err, data) {
if (err) {
// Failed saving to S3
log.error('Failed saving to S3', err);
}
callback(err);
}
);
});
取消注释fileWriteSync和fileReadSync,它可以正常工作。
在两种情况下console.log(x)命令的输出: BAD:
缓冲区c3 bf c3 98 c3 bf c3 a0 00 10 4a 46 49 46 00 01 01 01 00 01 00 01 00 00 c3 bf c3 9b 00 43 00 06 04 05 06 05 04 06 06 05 06 07 07 06 08 0a 10 0a 0a 09 09 ...>
GOOD:
缓冲区ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 01 00 01 00 00 ff db 00 43 00 06 04 05 06 05 04 06 06 05 06 07 07 06 08 0a 10 0a 0a 09 09 0a 14 0e 0f 0c 10 ...>
你可以看到好的jpeg是合适的jpeg,坏的虽然包含类似的序列,如4a 46 49 46 = JFIF,但有些字节是关闭的,并且有移位,整个文件大约增加20%in不好的情况。
与编码有关?我已经尝试了几件事,但此时我迷失了。
谢谢!
更新#1: 显然它与UTF编码有关,但我仍然不完全理解在这种情况下会发生什么。显然c3 bf c3 98 c3 bf c3 a0 00 10 4a 46 49 46 00 01是UTF编码:
U+00FF LATIN SMALL LETTER Y WITH DIAERESIS character (ÿ)
U+00D8 LATIN CAPITAL LETTER O WITH STROKE character (Ø)
U+00FF LATIN SMALL LETTER Y WITH DIAERESIS character (ÿ)
U+00E0 LATIN SMALL LETTER A WITH GRAVE character (à)
U+0000 <control> character
U+0010 <control> character
U+004A LATIN CAPITAL LETTER J character
U+0046 LATIN CAPITAL LETTER F character
U+0049 LATIN CAPITAL LETTER I character
U+0046 LATIN CAPITAL LETTER F character
U+0000 <control> character
U+0001 <control> character
当FF D8 FF ..正是我所期待的。
我知道如何在没有临时文件的情况下使代码工作(将var x = new Buffer(stdout); 替换为var x = new Buffer(stdout,'binary'))
但是我仍然不能说我完全理解这里发生了什么,这应该没有Buffer()包装,哪个组件有问题? ImageMagick的?缓冲器?
答案 0 :(得分:1)
这显然已经很晚了,但我自己也遇到了这个问题,这就是我如何运作的;
ImageMagick.resize(params, function(err, stdout, stderr) {
// Handle errors
// Save the output of imagemagick to S3
S3.putObject({
Bucket: bucketName,
Key: fileName,
Body: new Buffer(stdout, "binary")
}).promise().then(function(data){
// Success
}).catch(function(err){
// Error
});
});
关键部分显然是; new Buffer(stdout, "binary")
。如果您不知道响应是否为缓冲区,则可以使用Buffer.isBuffer
方法并执行以下操作;
var body = ( Buffer.isBuffer(stdout) ? stdout : new Buffer(stdout, "binary") );
答案 1 :(得分:0)
不确定OP是否解决了问题,但我也遇到了类似的问题,即上传到S3的图像比原始文件大。你能告诉我stdout包含什么(即它是原始字节流吗?)
我通过设置body:参数来使用base64编码缓冲区而不是二进制缓冲区解决了这个问题。我不完全确定为什么这解决了这个问题,但我怀疑它与此有关:
当需要对需要存储的二进制数据进行编码并通过旨在处理文本数据的媒体进行传输时,通常会使用Base64编码方案。这是为了确保数据在运输过程中保持完好无需修改。
来源:MDN