2017-04-08 19 views
0

としてSVGのエンコードは、私はHTMLメールに使用するbase64で画像としてサーバーサイドD3 - Base64のイメージ

をD3チャートをエンコードしようとしているこれまでのところ私が持っている:

var express = require('express'); 
var app = express(); 
var jsdom = require('jsdom'); 

app.get('/chart', function (request, response) { 
    try { 
     jsdom.env(
      "<html><body><svg id=\"svg\"></svg></body></html>", 
      ['http://d3js.org/d3.v3.min.js'], 
      function (err, window) { 
       var svg = window.d3.select("svg") 
        .attr("width", 100) 
        .attr("height", 100); 

       svg.append("rect") 
        .attr("x", 10) 
        .attr("y", 10) 
        .attr("width", 80) 
        .attr("height", 80) 
        .style("fill", "orange"); 

       var encoded = ...; // How do I now encode this? 

       response.send({ 
        "html": window.d3.select("body").html(), 
        "encoded": encoded 
       }); 
      } 
     ); 
    } catch (err) { 
     console.error(err); 
    } 
}); 

// Run Server 
var port = process.env.PORT || 8305; 
var server = app.listen(port, function() { 
    var host = server.address().address; 
    console.log('App listening at http://%s:%s', host, port); 
}); 

これは、出力します便利であるSVGのhtmlは、しかし、私はまた、私は私のHTML形式の電子メールで使用できるよう、以下のようなものが含まれている必要があります秒の応答フィールドencodedたい:

"encoded": "data:image/png;base64,iVBORw0KGgoAAAANSUhEU...etc" 

は、どのように私はこのSVGをエンコードするのですか?可能であればファイルの書き込みを避け、SVGから直接エンコードされた画像に行きたいと思います。また、電子メールでSVGを使用できることは承知していますが、むしろエンコードされたイメージ形式になっています。ありがとう!

答えて

3
NodeJSを用いD3チャートを構築し、(ほとんどのクラウドホスティングのためのneccessary)

let express = require('express'); 
let app = express(); 

let jsdom = require('jsdom'); 
let Buffer = require('buffer').Buffer; 
let svg2png = require('svg2png'); 

app.post('/chart', function (request, response) { 
    try { 
     jsdom.env(
      "<svg id=\"svg\"></svg>", 
      ['http://d3js.org/d3.v3.min.js'], 
      function (err, window) { 
       let svg = window.d3.select("svg") 
        .attr("width", 100) 
        .attr("height", 100) 
        .attr("xmlns", "http://www.w3.org/2000/svg"); 

       svg.append("rect") 
        .attr("x", 10) 
        .attr("y", 10) 
        .attr("width", 80) 
        .attr("height", 80) 
        .style("fill", "orange"); 

       let data = "data:image/png;base64,"; 
       let svgString = svg[0][0].outerHTML; 
       let buffer = new Buffer("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + svgString); 
       let promise = svg2png(buffer, {width: 300, height: 400}); // This options block is optional but height and width should be specified on the SVG HTML otherwise 
       promise.then(buffer => { 
        let dataURI = data + buffer.toString('base64'); 
        response.set('Content-Type', 'application/json'); 
        response.send({ 
         "html": svgString, 
         "encoded": dataURI 
        }); 
       }); 
      } 
     ); 
    } catch (err) { 
     console.warn(err); 
    } 
}); 

// Run Server 
let port = process.env.PORT || 8305; 
let server = app.listen(port, function() { 
    let host = server.address().address || 'localhost'; 
    console.log('Example app listening at http://%s:%s', host, port); 
}); 
ファイルストレージを使用せずに符号化されたPNGに変換

完全なソリューション

レスポのフィールドencoded NSEは使用してHTML形式のメールで使用することができます:

<img src="{encoded-value}"/> 

例えば

<img src="data:image/png;base64,iVBORw0KGgoAAA..."/> 
1

これをpngイメージとして送信するには、まず実際の問題であるsvgをラスタライズする必要があります。これはいくつかの場所で回答されていますが、this oneには数多くの優れた解決策があります。おそらくimagemagickを変換に使用するべきです。あなたは中間ファイルへの書き込みを避けたいので、その答えはコンバータのstdinにsvgの内容をパイプすることができることを示唆しています。

受信バッファーはおそらくdirectly encoded to base64です。

+0

おかげで、私は、ファイルシステムへの書き込みを許可されていれば、それは物事がかなり異なるになるだろうか? – Edd

+0

その場合、コンバータにsvgをパイプするのではなく、svgをファイルに保存して、ファイル名をコンバータに渡します。だから、それほど違いはありません。いくつかのヒントについては、imagemagickのドキュメントを見てください。 – RecencyEffect

6

document内または.attr()<svg>ノードで"http://www.w3.org/2000/svg"へのルート<svg>ノードで"xmlns"属性を設定します。我々は<media type>image/svg+xmlであろうことを知っているので

data URIスキームは

data:[<media type>][;base64],<data> 

から成り、我々はデータを得られるのbase64表現したいことを、我々は<svg>base64表現を連結先となる変数を定義することができます。

let data = "data:image/svg+xml;base64,"; 

その後、我々は、パラメータとして.outerHTML<svg>の要素svgString

// optionally preceded by `XML` declaration `<?xml version="1.0" standalone="yes"?>` 
let svgString = svg[0][0].outerHTML; 

コールbtoa()を取得

btoa(data)メソッドは、 "InvalidCharacterError" DOMExceptionかのデータをスローする必要があります含むコードポイントが で、U + 00FFより大きい任意の文字。そうでない場合、ユーザエージェントは、n番目のオクテットオクテットのシーケンスがデータN番目の文字のコードポイントの8ビット表現 ある にデータをを変換する必要があり、その後 BASE64アルゴリズムを適用する必要がありますそのオクテットのシーケンスに変換し、 結果を返します。[RFC4648]

let base64 = window.btoa(svgString); 
// concatenate `data` and `base64` 
let dataURI = data + base64; 

response.send({ 
       "html": window.d3.select("body").html(), 
       "encoded": dataURI 
      }); 

let svg = window.d3.select("svg") 
 
    .attr("xmlns", "http://www.w3.org/2000/svg") 
 
    .attr("width", 100) 
 
    .attr("height", 100); 
 

 
svg.append("rect") 
 
    .attr("x", 10) 
 
    .attr("y", 10) 
 
    .attr("width", 80) 
 
    .attr("height", 80) 
 
    .style("fill", "orange"); 
 

 
let data = "data:image/svg+xml;base64,"; 
 
let svgString = svg[0][0].outerHTML; 
 
let base64 = window.btoa(svgString); 
 
let dataURI = data + base64; 
 

 
console.log(dataURI); 
 

 
document.querySelector("iframe").src = dataURI;
<script src="https://d3js.org/d3.v3.min.js"></script> 
 
<svg></svg> 
 
<iframe></iframe>

+0

残念なことにHTMLの電子メールでscriptタグを使用できるとは思えません。また、img上でiframeを使用する利点は何ですか? – Edd

+0

@ Ed0906 '