NodeJS base64イメージのエンコード/デコードがうまくいかない

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

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

助けて! (OSX Lionのnode.js 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) {});
});
ベストアンサー

私はエンコーディング引数の使い方を誤解していると思います。エンコーディング
‘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) {});
});

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です