2010-09-14 16 views
15

Usando Node v0.2.0 Estoy tratando de obtener una imagen de un servidor, convertirla en una cadena base64 y luego incrustarla en la página en una etiqueta de imagen. Tengo el siguiente código:Node.js base64 codifica una imagen descargada para su uso en URI de datos

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

Nota: Este código requiere "express" y "request". Y por supuesto, node. Si tiene npm instalado, debe ser tan simple como "npm install express" o "npm install request".

Desafortunadamente, esto no funciona como se esperaba. Si hago la conversión con la Google logo, entonces me sale el siguiente al inicio de la cadena:

77 + 9UE5HDQoaCgAAAA1JSERSAAABEwAAAF8IAwAAAO +/VE +/VE +/vSkAAAMAUExURQBzCw5xGiNmK0t + U ++/vQUf77 + 9BiHvv70WKO +/vQkk77 + 9D

Sin embargo, si uso un Base64 encoder en línea con la misma imagen, entonces funciona perfectamente. La cadena comienza así:

iVBORw0KGgoAAAANSUhEUgAAARMAAABfCAMAAAD8mtMpAAADAFBMVEUAcwsOcRojZitLflOWBR + aBiGQFiipCSS8DCm1Cya1FiyNKzexKTjDDSrLDS

¿Dónde voy equivocada de que esto no está funcionando correctamente? He intentado tantas implementaciones js base64 diferentes y todas no funcionan de la misma manera. Lo único que puedo pensar es que estoy tratando de convertir lo incorrecto en base64, pero ¿qué debo convertir si ese es el caso?

Respuesta

13

El problema es la codificación y el almacenamiento de datos binarios en cadenas de javascript. Hay una sección bastante buena en esto bajo Buffers al http://nodejs.org/api.html.

Desafortunadamente, la manera más fácil de solucionar esto fue cambiar la solicitud npm. Tuve que agregar response.setEncoding('binary'); en la línea 66 justo debajo de var buffer; en /path/to/lib/node/.npm/request/active/package/lib/main.js. Esto funcionará bien para esta solicitud pero no para otras. Es posible que desee hackearlo para que esto solo se configure en función de alguna otra opción aprobada.

Luego cambié var buf = new Buffer(body) a var buf = new Buffer(body, 'binary');. Después de esto, todo funcionó bien.

Otra forma de hacer esto, si realmente no desea tocar el npm de la solicitud, sería pasar un objeto que implementa la secuencia de escritura en el argumento responseBodyStream para solicitar. Este objeto almacenaría los datos transmitidos desde la respuesta en su propio búfer. Tal vez hay una biblioteca que hace esto ya ... no estoy seguro.

Voy a dejarlo aquí por ahora, pero siéntete libre de comentar si quieres que aclare algo.

EDITAR

Echa un vistazo a los comentarios.Nueva solución en http://gist.github.com/583836

+0

Gracias, esto funciona, pero realmente no me gusta la idea de editar el paquete de solicitud para que funcione. ¿Cómo implementaría exactamente un objeto de secuencia de escritura? No puedo entender cómo crear uno. ¡Cualquier ayuda sería realmente apreciada! – betamax

+0

Encontré una buena implementación de secuencia modificable en http://github.com/substack/node-bufferlist. Aquí hay una versión actualizada del código que no necesita modificar la biblioteca de solicitudes: http://gist.github.com/583836. – bxjx

+0

que funcionan para usted? – bxjx

8

el siguiente código (disponible en 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; 
    }); 
}); 

también debe producir un URI de datos sin necesidad de módulos externos.

1

Esto funciona para mí usando solicitud:

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

No hay necesidad de buffers intermedios. La clave es establecer la codificación en nulo.

Cuestiones relacionadas