Кодирование / декодирование изображения NodeJS base64 не совсем работает - PullRequest
33 голосов
/ 13 ноября 2011

Я пытался обработать сохранение изображений, отправленных POSTed на nodeJS (и платформу Express) в базу данных, и у меня возникли некоторые проблемы.Игнорируя всю веб-обработку, я думаю, что я сузил проблему до способа, которым кодирование base64 происходит в узле.Я считаю, что приведенный ниже упрощенный пример должен работать, но выходное изображение всегда искажается.

В примере (1) загрузка изображения (2) сохраняет копию if (image_orig), чтобы подтвердить, что узел может правильно прочитать файл.Это всегда работает.(3) Я беру изображение и base64 кодирую его содержимое, (4) затем декодирую его.Окончательное выходное изображение (image_decoded) всегда повреждено.

Помогите!(node.js 0.6.0 в OSX Lion)

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

Ответы [ 2 ]

103 голосов
/ 13 ноября 2011

Я думаю, вы немного неправильно понимаете использование аргумента кодирования.Если вы собираетесь указать кодировку «двоичный», то вам нужно делать это последовательно.Но на самом деле это совсем не нужно.Вы, кажется, путаете использование 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) {});
});
16 голосов
/ 23 декабря 2013

Чуть лучшим решением будет удаление всех возможных типов пантомимы:

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

Это дополнение к ответу @ Herve.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...