2013-10-24 59 views
2

我在使用imagemagick处理图像然后将其上传到S3时出现问题。产生的对象具有不同(更大)的尺寸并且似乎损坏。如果我进行一个中间步骤并将输出保存到本地tmp文件并将其读回,那么上传结果一切似乎都很好。这是不起作用的代码。node.js将imagemagick的输出上传到AWS S3

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 C3 BF A0 00 10 4A 46 49 46 00 01 01 01 00 01 00 01 00 00 C3 C3 BF 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 d 8 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,坏一个虽然包含像图4a相似的序列46 49 46 = JFIF,然而,一些字节都关闭,并且有变化,所述在不好的情况下整个文件大约增加20%。

与编码有关吗?我已经尝试了几件事情,但在这一点上我迷失了方向。

谢谢!

更新#1: 显然,这是关系到UTF编码,但我还是不完全理解在这种情况下会发生什么。显然C3 BF C3 98 C3 C3 BF 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 FF D8 ..正是我期待。

我知道如何使代码工作,而临时文件(替代VAR X =新的缓冲区(标准输出);使用var X =新的缓冲区(标准输出, '二进制')

不过我仍然不能说我完全理解这里发生了什么,这应该不用Buffer()来包装,哪个组件有问题? ImageMagick的?缓冲?

+0

哇,这是一个奇怪的问题。措辞措辞良好的问题和有趣的问题。我会看看我是否可以在今天的某个时间查看:) –

+0

出于好奇,如果不将stdout放入新的缓冲区对象,会发生什么?它是否以node-imagemagick作为字符串出来?如果它作为一个缓冲区无论如何,腐败可能是双缓冲区包装... –

+0

你尝试了'身体:标准输出',在你的putObject选项发送标准输出没有包装在不必要的缓冲区? –

回答

0

不知道OP是否解决了这个问题,但我也有类似的问题,其中上传到S3的图像比原始文件大。你能告诉我什么stdout包含(即,它是一个原始字节流?)

我解决了这个问题,通过设置我的身体:参数使用base64编码的缓冲区,而不是二进制缓冲区。我不完全确定为什么这解决了这个问题,但我怀疑它与此有关:

当需要对需要存储和传输的二进制数据进行编码时,通常使用Base64编码方案对媒体,旨在处理文本数据。这是为了确保数据在运输过程中保持完整无需修改。

来源:MDN

+1

无论如何,你可以展示你的解决方案,我目前正在处理同样的问题。 – Lion789

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"));