Создание файла JPG с помощью Node.JS

На моем сервере node.js я загружаю файл с другого сервера. Загруженный файл представляет собой данные изображения JPG, закодированные с помощью Base64 два раза, это означает, что мне нужно декодировать его 2 раза. Дан мой код.

var base64DecodedFileData = new Buffer(file_data, 'base64').toString('binary');
var tmp = base64DecodedFileData.split("base64,");
var base64DecodedFileData = new Buffer(tmp[1], 'base64').toString('binary');                                                                                                           
var file = fs.createWriteStream(file_path, stream_options);
file.write(base64DecodedFileData);
file.end();

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

Я сравнил его с реальным изображением, начало и конец обоих файлов выглядят нормально, но что-то не так в моем созданном файле. Сконструированный файл также больше по размеру, чем исходный.

PS: я делаю разделение перед декодированием во второй раз, потому что данные после первого декодирования начинаются с

данные:; base64, СТАРТ ДАННЫХ

Есть предположения. Фаррух Аршад.


person Farrukh Arshad    schedule 22.09.2012    source источник
comment
Просто чтобы уточнить - почему он кодируется дважды?   -  person DeadAlready    schedule 22.09.2012
comment
Это просто способ, которым сервер (откуда я загружаю файл) загружает файлы.   -  person Farrukh Arshad    schedule 22.09.2012


Ответы (1)


Я решил Свою проблему. Проблема, похоже, в декодировании из node.js, поэтому я написал дополнение C++ для выполнения этой работы. Вот код. Я почти уверен, что проблема останется, если у нас есть файл изображения, закодированный только один раз.

.js-файл

ModUtils.generateImageFromData (данные_файла, путь_к_файлу);

Надстройка c++: используется кодировщик/декодер base64 C++ с http://www.adp-gmbh.ch/cpp/common/base64.html

#define BUILDING_NODE_EXTENSION
#include <node.h>
#include <iostream>
#include <fstream>
#include "base64.h"

using namespace std;
using namespace v8;

static const std::string decoding_prefix = 
"data:;base64,";

// --------------------------------------------------------
//  Decode the image data and save it as image
// --------------------------------------------------------
Handle<Value> GenerateImageFromData(const Arguments& args) {
HandleScope scope;

// FIXME: Improve argument checking here.
// FIXME: Add error handling here.

if ( args.Length() < 2) return v8::Undefined();

Handle<Value> fileDataArg = args[0];
Handle<Value> filePathArg = args[1];
String::Utf8Value encodedData(fileDataArg);
String::Utf8Value filePath(filePathArg);
std::string std_FilePath = std::string(*filePath);

// We have received image data which is encoded with Base64 two times
// so we have to decode it twice.
std::string decoderParam = std::string(*encodedData);
std::string decodedString = base64_decode(decoderParam);

// After first decoding the data will also contains a encoding prefix like 
    // data:;base64,
// We have to remove this prefix to get actual encoded image data.
std::string second_pass = decodedString.substr(decoding_prefix.length(),     (decodedString.length() - decoding_prefix.length()));
std::string imageData = base64_decode(second_pass);

// Write image to file
ofstream image;
image.open(std_FilePath.c_str());
image << imageData;
image.close();

return scope.Close(String::New(" "));
//return scope.Close(decoded);
}

void Init(Handle<Object> target) {

// Register all functions here
target->Set(String::NewSymbol("generateImageFromData"),
    FunctionTemplate::New(GenerateImageFromData)->GetFunction());
}

NODE_MODULE(modutils, Init);

Надеюсь, это поможет кому-то другому.

person Farrukh Arshad    schedule 22.09.2012