0%

Html2Image

如何实现一个简单的HTML生成Image的服务?

实现要素:

  1. Html渲染引擎 + 截图
  2. Web Server

实现方案

PhantomJS

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

  • webpage模块
    • content变量 用于设置需要渲染的web页面内容
    • onLoadFinished回调 用于在web页渲染完成后,执行相应的操作
    • renderBuffer方法 用于获取渲染完成后的图片数据(Uint8ClampedArray格式)
    • renderBase64方法 用于获取渲染完成后的图片数据(Base64编码String格式)
  • webserver模块
    • 用于实现WebServer

问题&解决

  1. PhantomJS的wiki定义了renderBuffer方法但是没有实现?
    使用renderBase64方法获取图片数据。
  2. 上一问题的解决方案解决了获取的数据问题,但没有解决如何将获取的数据输出为图片的问题,如何解决?
    将Base64字符串解码成二进制字符串。
  3. 渲染的图片上的文字显示效果差?
    在系统中安装适当的字体。

实现Demo

Base64解码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

var Base64Binary = {
_keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',

decode: function(input){
if(input.length % 4 || !(input.match(/^[A-Za-z0-9\+\/]+(={0,2})$/)){
return null;
}
var str = '';
var code_1, code_2, code_3, code_4;
for(var j = 0; j < input.length;){
// 取本组第1、2位编码
code_1 = this._keyStr.indexOf(input.charAt(j++));
code_2 = this._keyStr.indexOf(input.charAt(j++));
str += String.fromCharCode(((code_1 << 2) & 0xFC) | ((code_2 >> 4) & 0x03));
// 取本组第3位编码
code_3 = this._keyStr.indexOf(input.charAt(j++));
if(0x40 === code_3){
break;
}
str+= String.fromCharCode(((code_2 << 4) & 0xF0) | ((code_3 >> 2) & 0x0F));
// 取本组第4位编码
code_4 = this._keyStr.indexOf(input.charAt(j++));
if(0x40 === code_4){
break;
}
str+= String.fromCharCode(((code_3 << 6) & 0xC0) | ((code_4 >> 0) & 0x3F));
}
return str;
}
};

Html2Image服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

var server = require('webserver').create();

server.listen(8001, function(request, response) {
var format = 'png';

var page = require('webpage').create();

page.viewportSize = {
width: 800,
height: 600
};

page.content = request.post;

page.onLoadFinished = function(status) {
// Buffer is an binary string
var buffer_base64 = page.renderBase64(format);
buffer = Base64Binary.decode(buffer_base64);

response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'image/' + format
};

// Pass the Buffer to 'write' to send the binary string to the client
response.setEncoding('binary');
response.write(buffer);
response.close();
};

});