应公司领导需求,最近在做一个类似“掘金”的插件,获取gitlab上公司的技术文档,仅供内部使用。
当通过接口去获取数据时,发现返回的json数据是base64编码的,根本无法阅读,只能解码。
所谓Base64,就是选出64个字符作为一个基本字符集(A-Z,a-z,0-9,+,/,再加上作为垫字的"=",实际是65个字符),其它所有符号都转换成这个字符集中的字符。
例如:
“dog”:
d: ASCII值 100 ,二进制为 0110 0100
o: ASCII值 111 ,二进制为 0110 1111
g: ASCII值 103,二进制为 0110 0111
这24个二进制位 0110 0100 0110 1111 0110 0111 分为四组:
011001 000110 111101 100111
每组前面加两个00,即:
00011001 00000110 00111101 00100111
对应码值分别为:25、6、61、39
查找下表,可以知道得到编码后的字符串为:ZG9n
测试一下:(Base64见文末代码,不是js自带的哦)
ASCII值 | 符号 | ASCII值 | 符号 | ASCII值 | 符号 | ASCII值 | 符号 |
---|---|---|---|---|---|---|---|
0 | A | 17 | R | 34 | i | 51 | z |
1 | B | 18 | S | 35 | j | 52 | 0 |
2 | C | 19 | T | 36 | k | 53 | 1 |
3 | D | 20 | U | 37 | l | 54 | 2 |
4 | E | 21 | V | 38 | m | 55 | 3 |
5 | F | 22 | W | 39 | n | 56 | 4 |
6 | G | 23 | X | 40 | o | 57 | 5 |
7 | H | 24 | Y | 41 | p | 58 | 6 |
8 | I | 25 | Z | 42 | q | 59 | 7 |
9 | J | 26 | a | 43 | r | 60 | 8 |
10 | K | 27 | b | 44 | s | 61 | 9 |
11 | L | 28 | c | 45 | t | 62 | + |
12 | M | 29 | d | 46 | u | 63 | / |
13 | N | 30 | e | 47 | v | ||
14 | O | 31 | f | 48 | w | ||
15 | P | 32 | g | 49 | x | ||
16 | Q | 33 | h | 50 | y |
那如果字节数不足3呢?
a)2个字节的情况:将这2个字节的一共16个二进制位,按照上面的规则,转成三组(6,6,4),最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个"="号。
比如,“Ma"这个字符串是两个字节,可以转化成三组00010011、00010110、00000100以后,对应Base64值分别为T、W、E,再补上一个”="号,因此"Ma"的Base64编码就是TWE=。
b)1个字节的情况:将这1个字节的8个二进制位,按照上面的规则转成2组(6,2),最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个"="号。
比如,“M"这个字母是一个字节,可以转化为二组00010011、00010000,对应的Base64值分别为T、Q,再补上二个”="号,因此"M"的Base64编码就是TQ==。
了解了编码规则之后,解码就很容易理解了,就是编码过程的逆过程
知道了编码解码规则之后,就是编程实现了。代码如下:
var Base64 = {
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode: function(e) {
var t = "";
var n, r, i, s, o, u, a;
var f = 0;
e = Base64._utf8_encode(e);
while (f < e.length) {
n = e.charCodeAt(f++);
r = e.charCodeAt(f++);
i = e.charCodeAt(f++);
s = n >> 2;
o = (n & 3) << 4 | r >> 4;
u = (r & 15) << 2 | i >> 6;
a = i & 63;
if (isNaN(r)) {
u = a = 64
} else if (isNaN(i)) {
a = 64
}
t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
}
return t
},
decode: function(e) {
var t = "";
var n, r, i;
var s, o, u, a;
var f = 0;
e = e.replace(/[^A-Za-z0-9+/=]/g, "");
while (f < e.length) {
s = this._keyStr.indexOf(e.charAt(f++));
o = this._keyStr.indexOf(e.charAt(f++));
u = this._keyStr.indexOf(e.charAt(f++));
a = this._keyStr.indexOf(e.charAt(f++));
n = s << 2 | o >> 4;
r = (o & 15) << 4 | u >> 2;
i = (u & 3) << 6 | a;
t = t + String.fromCharCode(n);
if (u != 64) {
t = t + String.fromCharCode(r)
}
if (a != 64) {
t = t + String.fromCharCode(i)
}
}
t = Base64._utf8_decode(t);
return t
},
_utf8_encode: function(e) {
e = e.replace(/rn/g, "n");
var t = "";
for (var n = 0; n < e.length; n++) {
var r = e.charCodeAt(n);
if (r < 128) {
t += String.fromCharCode(r)
} else if (r > 127 && r < 2048) {
t += String.fromCharCode(r >> 6 | 192);
t += String.fromCharCode(r & 63 | 128)
} else {
t += String.fromCharCode(r >> 12 | 224);
t += String.fromCharCode(r >> 6 & 63 | 128);
t += String.fromCharCode(r & 63 | 128)
}
}
return t
},
_utf8_decode: function(e) {
var t = "";
var n = 0;
var r = c1 = c2 = 0;
while (n < e.length) {
r = e.charCodeAt(n);
if (r < 128) {
t += String.fromCharCode(r);
n++
} else if (r > 191 && r < 224) {
c2 = e.charCodeAt(n + 1);
t += String.fromCharCode((r & 31) << 6 | c2 & 63);
n += 2
} else {
c2 = e.charCodeAt(n + 1);
c3 = e.charCodeAt(n + 2);
t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
n += 3
}
}
return t
}
}
window有两个函数atob、btoa,但是这两个函数并不支持Unicode字符的编码,需结合encodeURIComponent、decodeURIComponent函数来使用。具体介绍请移步我的博客:
JavaScript函数btoa、atob
前端在实现页面时,对于一些简单图片,通常会选择将图片内容直接内嵌在页面中,避免不必要的外部资源加载,增大页面加载时间,但是图片数据是二进制数据,该怎么嵌入呢?绝大多数现代浏览器都支持一种名为 Data URL 的特性,允许使用Base64对图片或其他文件的二进制数据进行编码,将其作为文本字符串嵌入网页中。
例如,我将本地一张图片进行Base64编码后(推荐一个在线图片转换工具:http://imgbase64.duoshitong.com/ ),其编码结果如下:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAACRCAYAAAAl8ZFnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJ0SURBVHhe7dYxalRRFIBhl+AKXEzqNNZuwzKNnVZTBRtJkyUELCysBRtxHdM9El5k4MkLpMhwYQb8rd5XfN053c+599U0TQtUBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERWrzQd3//rXMtzdP7n/+GM5wvk0HNV/vluXN6xf+XL0fznKezQa1XqbjmJ49fL0b7nDaZoMaXadnjx8/DHc4bbNBrdGMYlqt/6nRDqcJ6sjh8mKZ9vvhDqcJ6ojn7t8ISlApQQkqJShBpQQlqJSgBJUSlKBSghJUSlCCSglKUClBCSolKEGlBCWolKAElRKUoFKCElRKUIJKCUpQKUEJKiUoQaUEJaiUoASVEpSgUoISVEpQgkoJSlApQQkqJShBpQQlqJSgBJUSlKBSghJUSlCCSglKUClBCSolKEGlBCWolKAElRKUoFKCElRKUIJKCUpQKUEJKiUoQaUEJaiUoASVEpSgUoISVEpQgkoJSlApQQkqJShBpQQlqJSgBJUSlKBSghJUSlCCSglKUClBCSolKEGlBCWolKAElRKUoFKCElRqu0HtPgnqP9hsUA/fvw2Dmm9vhvOcZ7NBrQ7v3r6I6XB5sUz7/XCW82w6qNX85fPTMzdf78QU2HxQtARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQhKblL8jJczAt5hHJAAAAAElFTkSuQmCC
读者可将此Data URL 复制到浏览器地址栏试一下,发现可以解析出此图片。
用此方式可以将图片直接内嵌到网页中:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAACRCA..."/>