Node.js base64 кодирует загруженное изображение для использования в URI данных
Использование Node v0.2.0 Я пытаюсь извлечь изображение с сервера, преобразовать его в строку base64 и затем вставить его на страницу в тег изображения. У меня есть следующий код:
var express = require('express'),
request = require('request'),
sys = require('sys');
var app = express.createServer(
express.logger(),
express.bodyDecoder()
);
app.get('/', function(req, res){
if(req.param("url")) {
var url = unescape(req.param("url"));
request({uri:url}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var data_uri_prefix = "data:" + response.headers["content-type"] + ";base64,";
var buf = new Buffer(body);
var image = buf.toString('base64');
image = data_uri_prefix + image;
res.send('<img src="'+image+'"/>');
}
});
}
});
app.listen(3000);
Примечание. Этот код требует " express" и " request". И, конечно, node. Если у вас установлена npm, она должна быть такой же простой, как "npm install express" или "npm install request".
К сожалению, это не работает должным образом. Если я сделаю преобразование с логотипом Google, тогда я получаю следующее в начале строки:
77 + 9UE5HDQoaCgAAAA1JSERSAAABEwAAAF8IAwAAAO +/ве +/ве +/vSkAAAMAUExURQBzCw5xGiNmK0t + U ++/vQUf77 + 9BiHvv70WKO +/vQkk77 + 9D
Однако, если я использую онлайн-код Base64 encoder с тем же изображением, то он отлично работает. Строка начинается следующим образом:
iVBORw0KGgoAAAANSUhEUgAAARMAAABfCAMAAAD8mtMpAAADAFBMVEUAcwsOcRojZitLflOWBR + aBiGQFiipCSS8DCm1Cya1FiyNKzexKTjDDSrLDS
Где я ошибаюсь, что это работает неправильно? Я пробовал так много различных js base64-реализаций, и все они не работают одинаково. Единственное, о чем я могу думать, это то, что я пытаюсь преобразовать неправильную вещь в base64, но что мне нужно преобразовать, если это так?
Ответы
Ответ 1
Проблема заключается в кодировании и хранении двоичных данных в строках javascript. Там довольно хороший раздел об этом под буферами в http://nodejs.org/api.html.
К сожалению, самый простой способ исправить это включает изменение запроса npm. Мне пришлось добавить response.setEncoding('binary');
в строке 66 чуть ниже var buffer;
в /path/to/lib/ node/.npm/request/active/package/lib/main.js. Это будет отлично работать для этого запроса, но не для других. Возможно, вы захотите его взломать, чтобы это было задано только на основе другого переданного параметра.
Затем я изменил var buf = new Buffer(body)
на var buf = new Buffer(body, 'binary');
. После этого все работало нормально.
Другой способ сделать это, если вы действительно не хотите касаться запроса npm, - это передать объект, который реализует Writable Stream в аргументе responseBodyStream для запроса. Затем этот объект будет хранить потоковые данные из ответа в собственном буфере. Может быть, есть библиотека, которая делает это уже... Я не уверен.
Я собираюсь оставить его здесь на данный момент, но не стесняйтесь комментировать, если вы хотите, чтобы я что-то разъяснил.
ИЗМЕНИТЬ
Ознакомьтесь с комментариями. Новое решение в http://gist.github.com/583836
Ответ 2
Следующий код (доступен в https://gist.github.com/804225)
var URL = require('url'),
sURL = 'http://nodejs.org/logo.png',
oURL = URL.parse(sURL),
http = require('http'),
client = http.createClient(80, oURL.hostname),
request = client.request('GET', oURL.pathname, {'host': oURL.hostname})
;
request.end();
request.on('response', function (response)
{
var type = response.headers["content-type"],
prefix = "data:" + type + ";base64,",
body = "";
response.setEncoding('binary');
response.on('end', function () {
var base64 = new Buffer(body, 'binary').toString('base64'),
data = prefix + base64;
console.log(data);
});
response.on('data', function (chunk) {
if (response.statusCode == 200) body += chunk;
});
});
также должен создавать URI данных, не требуя каких-либо внешних модулей.
Ответ 3
Это работает для меня с использованием запроса:
const url = 'http://host/image.png';
request.get({url : url, encoding: null}, (err, res, body) => {
if (!err) {
const type = res.headers["content-type"];
const prefix = "data:" + type + ";base64,";
const base64 = body.toString('base64');
const dataUri = prefix + base64;
}
});
Нет необходимости в каких-либо промежуточных буферах. Ключ должен установить кодировку в значение null.