2011-11-13 10 views
27

nodeJS(およびエクスプレスフレームワーク)にポストされたイメージをデータベースに保存して処理する際に問題を抱えています。すべてのWeb処理を無視して、私はノードでbase64エンコーディングが起こっている方法に問題を絞り込んだと思う。私は、以下の単純化された例がうまくいくはずだと考えていますが、出力イメージは常に壊れています。NodeJS base64イメージのエンコーディング/デコードがうまくいかない

イメージ(2)にロードする例(1)は、(image_orig)のコピーを保存してノードがファイルを正しく読み取ることを確認します。これは常に動作します。 (3)イメージを取ってbase64でその内容をエンコードし、(4)それをデコードします。最終出力イメージ(image_decoded)は常に破損しています。

ヘルプ! (Node.jsのOSXライオンの0.6.0)は

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

私はあなたのencoding引数ビットの使用を誤解していると思います。エンコーディング 'binary'を指定する場合は、それを一貫して行う必要があります。しかし、本当にあなたはそれをまったく必要としません。あなたは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) {}); 
}); 

次の例は動作しますが、すべての時間が必要とされていないエンコーディングを変更するため、非常に非効率的であるが、私はちょうど明確にすることを示したいと思います。実際にDIDで特定のエンコーディングを使用する場合は、一貫性があることを確認する必要があります。これらの関数のすべてには符号化引数があります。

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) {}); 
}); 

これは正しい方法です。すべてをBufferにしておきます。

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

関連する問題