2013-10-24 58 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"));