2011-11-13 91 views
27

我一直在嘗試處理將保存的圖像發送到nodeJS(以及快速框架)到數據庫,並且遇到了一些麻煩。忽略所有的Web處理,我認爲我已經將問題縮小到了base64編碼在節點中發生的方式。我相信下面的簡單示例應該可以工作,但輸出圖像總是被損壞。NodeJS base64圖像編碼/解碼不起作用

加載到圖像(2)中的示例(1)保存if(image_orig)的副本以確認節點可以正確讀取文件。這總是有效的。 (3)我把圖像和base64編碼其內容,(4)然後解碼它。最終輸出圖像(image_decoded)始終損壞。

幫助! (node.js的0.6.0在OSX獅子)

console.log("starting"); 
process.chdir(__dirname); 

var fs = require("fs"); 

var image_origial = "image.jpg"; 
fs.readFile(image_origial, function(err, original_data){ 
    fs.writeFile('image_orig.jpg', original_data, function(err) {}); 
    var base64Image = new Buffer(original_data, 'binary').toString('base64'); 
    var decodedImage = new Buffer(base64Image, 'base64').toString('binary'); 
    fs.writeFile('image_decoded.jpg', decodedImage, function(err) {}); 
}); 

回答

95

我想你是誤會了編碼參數位的使用。如果你打算指定編碼'二進制',那麼你需要一直這樣做。但是,你真的不需要它。你似乎混淆了Buffer和二進制字符串的用法。

// This tells node to load the file into a Buffer 'original_data' because you 
// have not specified an encoding for the returned values. If you provided an 
// encoding, then original_data would be a string with that encoding. 
fs.readFile(image_origial, function(err, original_data){ 

    // This tells node to take that buffer, and write it to the new filename. 
    // Again no encoding is provided, so it will assume a Buffer or utf8 string. 
    fs.writeFile('image_orig.jpg', original_data, function(err) {}); 

    // This tells node to create a new buffer from the old buffer, which means 
    // it will iterate over original_data copying the bytes one at a time. But 
    // they will be identical buffers. It will ignore the 'binary' argument 
    // since the object you are passing isn't a string. 
    // Then it encodes the content of that Buffer to base64, which is fine. 
    var base64Image = new Buffer(original_data, 'binary').toString('base64'); 

    // Here you decode the base64 to a buffer, which is fine, but then you 
    // convert the buffer into a string with encoding 'binary'. This means that 
    // it is a string object whose code points are bytes of the buffer. 
    var decodedImage = new Buffer(base64Image, 'base64').toString('binary'); 

    // Here you try to write that String object to a file. Since the argument you 
    // have given is a string and you have not given an encoding argument for the 
    // write command, then it will assume that 'utf8' is the encoding. It will try to 
    // decode your binary string into a utf8 encoded buffer, and write that buffer. 
    // This will cause it to fail because that encoding conversion is wrong. 
    // Really through, 'binary' is just wrong to use. Buffers are already binary. 
    fs.writeFile('image_decoded.jpg', decodedImage, function(err) {}); 
}); 

下一個示例將工作,但因爲改變不需要所有的時間編碼效率非常低,但我只是想表明它是清楚的。如果你真的想要一個特定的編碼,你需要確保你是一致的。每個函數都有一個編碼參數。

fs.readFile(image_origial, 'binary', function(err, original_data){ 
    fs.writeFile('image_orig.jpg', original_data, 'binary', function(err) {}); 
    var base64Image = new Buffer(original_data, 'binary').toString('base64'); 
    var decodedImage = new Buffer(base64Image, 'base64').toString('binary'); 
    fs.writeFile('image_decoded.jpg', decodedImage, 'binary', function(err) {}); 
}); 

這是正確的做法。保持一切爲緩衝區,除非你使base64。

fs.readFile(image_origial, function(err, original_data){ 
    fs.writeFile('image_orig.jpg', original_data, function(err) {}); 
    var base64Image = original_data.toString('base64'); 
    var decodedImage = new Buffer(base64Image, 'base64'); 
    fs.writeFile('image_decoded.jpg', decodedImage, function(err) {}); 
}); 
+3

謝謝!這解決了它! – Evan

+0

感謝您的超級信息反饋!我也可以使用您的指導將圖像編碼爲base64。 – zzaman

+1

如何將'decodedImage'寫入響應流? –

11

稍微好一點的解決方法是將刪除所有MIME類型可能:

var buff = new Buffer(req.body.imageFile 
    .replace(/^data:image\/(png|gif|jpeg);base64,/,''), 'base64'); 
fs.writeFile('/file/path/', buff, function (err) { 
    console.log('done'); 
}); 

這是除了@埃爾韋的答案。

+0

爲什麼需要刪除mime類型? – user1575921

+2

元數據僅用於瀏覽器。如果你不刪除它節點存儲損壞的圖像。 – simo

+0

謝謝,我明白了 – user1575921