web-dev-qa-db-ja.com

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 "」が必要です。そしてもちろん、 ノード 。 npmをインストールしている場合は、「npminstallexpress」または「npminstallrequest」と同じくらい簡単なはずです。

残念ながら、これは期待どおりに機能しません。 Googleロゴ を使用して変換を行うと、文字列の先頭に次のように表示されます。

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

ただし、同じ画像でオンライン Base64エンコーダー を使用すると、完全に機能します。文字列は次のように始まります。

iVBORw0KGgoAAAANSUhEUgAAARMAAABfCAMAAAD8mtMpAAADAFBMVEUAcwsOcRojZitLflOWBR + aBiGQFiipCSS8DCm1Cya1FiyNKzexKTjDDSrLDS

これが正しく機能していないのはどこが間違っているのですか?私は非常に多くの異なるjsbase64実装を試しましたが、それらはすべて同じようには機能しません。私が考えることができる唯一のことは、間違ったものをbase64に変換しようとしているということですが、その場合は何を変換する必要がありますか?

15
betamax

問題は、バイナリデータをJavaScript文字列にエンコードして保存することです。 http://nodejs.org/api.html のBuffersの下にこれに関するかなり良いセクションがあります。

残念ながら、これを修正する最も簡単な方法は、リクエストnpmを変更することでした。 /path/to/lib/node/.npm/request/active/package/lib/main.jsの_var buffer;_のすぐ下の66行目にresponse.setEncoding('binary');を追加する必要がありました。これはこのリクエストでは正常に機能しますが、他のリクエストでは機能しません。これをハックして、他の渡されたオプションに基づいてのみ設定されるようにすることをお勧めします。

次に、var buf = new Buffer(body)var buf = new Buffer(body, 'binary');に変更しました。この後、すべてが正常に機能しました。

これを行う別の方法は、本当にリクエストnpmに触れたくない場合は、リクエストのresponseBodyStream引数に書き込み可能なストリームを実装するオブジェクトを渡すことです。このオブジェクトは、応答からストリーミングされたデータを独自のバッファーに格納します。多分これをすでに行っているライブラリがあります...私にはわかりません。

とりあえずここに残しておきますが、何か明確にしたいことがあればコメントしてください。

[〜#〜]編集[〜#〜]

コメントをチェックしてください。 http://Gist.github.com/583836の新しいソリューション

13
bxjx

次のコード( 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を生成する必要があります。

8
JFSIII

これは、リクエストを使用して私のために機能します:

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に設定することです。

1
Steven Spungin