2010-09-14 99 views
15

使用节点v0.2.0我试图从服务器获取图像,将其转换为base64字符串,然后将其嵌入到图像标记的页面中。我有以下代码:Node.js base64编码下载的图像以用于数据URI

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”一样简单。

不幸的是,这不能按预期工作。

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

:如果我做的 Google logo转换,然后我得到的字符串的开头以下

但是,如果我使用在线Base64 encoder具有相同的图像,那么它完美的作品。该字符串开头是这样的:

iVBORw0KGgoAAAANSUhEUgAAARMAAABfCAMAAAD8mtMpAAADAFBMVEUAcwsOcRojZitLflOWBR + aBiGQFiipCSS8DCm1Cya1FiyNKzexKTjDDSrLDS

我要去哪里错了,这是不正常工作?我尝试了很多不同的js base64实现,它们都不以相同的方式工作。我能想到的唯一的事情就是我试图将错误的东西转换为base64,但如果情况如此,我应该如何转换?

回答

13

问题是在JavaScript字符串中编码和存储二进制数据。在缓冲区http://nodejs.org/api.html下有一个相当不错的部分。

不幸的是,解决这个问题的最简单方法是更改​​请求npm。我必须在第66行添加response.setEncoding('binary');,位于/path/to/lib/node/.npm/request/active/package/lib/main.js的var buffer;以下。这对于此请求可以正常工作,但对其他人无效。您可能想要对其进行破解,以便仅根据其他已通过的选项进行设置。

然后我将var buf = new Buffer(body)更改为var buf = new Buffer(body, 'binary');。之后,一切正常。

另一种方法来做到这一点,如果你真的不想触及请求npm,将传递一个实现可写入流的对象在responseBodyStream参数中请求。然后这个对象将来自响应的流数据存储在它自己的缓冲区中。也许有一个图书馆已经这样做......我不确定。

我现在要离开它,但如果你想让我澄清任何事情,请随时发表评论。

编辑

退房意见。在http://gist.github.com/583836

+0

谢谢,这是行得通的,但我不太喜欢编辑请求包让它工作的想法。如何实现一个可写的流对象?我无法弄清楚如何创建一个。任何帮助将非常感激! – betamax 2010-09-16 10:55:37

+0

在http://github.com/substack/node-bufferlist找到了一个很好的可写流实现。以下是不需要修改请求库的代码的更新版本:http://gist.github.com/583836。 – bxjx 2010-09-17 06:54:57

+0

适合你吗? – bxjx 2010-09-22 04:24:48

8

下面的代码新的解决方案(可在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,而无需任何外部模块。

1

这工作,使用请求我:

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

无需任何中间缓冲区。关键是将编码设置为空。