上一篇博客已经用纯 JS 实现了 Base64 的编解码处理,本来这个系列应该结束了,但是呢,人总是喜欢琢磨的,今天我要介绍另外一种更加另类、更加简单的处理方式。这里就要用到我们前面提到的 escape、unescape、encodeURI 和 decodeURI 这几个方法。关于这几个方法的作用我这里不做说明,想了解的可以去看我前面的博文。
思路
其实整体思路和上一篇一样,要把字符串转成一个个单字节字符。上一篇我们自己手写了一个 unicode2utf8 的函数,今天我们就不用自己手写了,用 encodeURI 函数就能实现,因为这个函数就是把 Javascript 中的 unicode 字符串转成类似于 "%E9%A3%8E" 的 utf-8 编码字符串。
然后就是把 utf-8 编码转成单字节字符,这里用到了 unescape 函数,这个函数会把 "%xx" 的十六进制编码字符串转成 ASCII 字符;把 "%uxxxx" 转成双字节 unicode 字符。
实现
这一篇博文其实就是把上一篇博文的 unicode2utf8 和 utf82unicode 这两个函数用 JS 中自带的方法去实现了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Javascipt 实现 Base64 编解码</title>
</head>
<body>
<div>
<span>输入要编码的字符串</span>
<input type="text" id="input">
</div>
<div>
<span>Base64 编码:</span>
<span id="enBase64"></span>
</div>
<div>
<span>Base64 解码:</span>
<span id="deBase64"></span>
</div>
<script>
// 一般的Base64编码字符
var commonbase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 对URL进行编码使用的字符
var urlBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
/*
Base64 是以字节为单位处理,所以我们处理的字符串应该是单字节字符串
这里我们默认是 utf-8 编码的字符串,因为 JS 无法识别 UTF-8 编码字符串,会识别成一个个单字节字符串
*/
function encodeBase64(hexStr){
var len = hexStr.length,
h1, h2, h3,
outStr = "";
for (var i = 0; i < len; i++) {
h1 = hexStr.charCodeAt(i);
if(i == len){ // 最后一个字符
outStr += commonbase64EncodeChars.charAt(h1 >> 2);
outStr += commonbase64EncodeChars.charAt((h1 << 4) & 0x3F);
outStr += "==";
} else if (i == len - 1) { // 倒数第二个字符
h2 = hexStr.charCodeAt(++i);
outStr += commonbase64EncodeChars.charAt(h1 >> 2);
outStr += commonbase64EncodeChars.charAt(((h1 << 4) & 0x3F) | (h2 >> 4));
outStr += commonbase64EncodeChars.charAt((h2 << 2) & 0x3F);
outStr += "=";
} else { // 剩余大于二个字符
h2 = hexStr.charCodeAt(++i);
h3 = hexStr.charCodeAt(++i);
outStr += commonbase64EncodeChars.charAt(h1 >> 2);
outStr += commonbase64EncodeChars.charAt(((h1 << 4) & 0x3F) | (h2 >> 4));
outStr += commonbase64EncodeChars.charAt((h2 << 2) & 0x3F | (h3 >> 6));
outStr += commonbase64EncodeChars.charAt(h3 & 0x3F);
}
}
return outStr;
}
function decodeBase64(str) {
var str = filterBase64(str),
len = str.length,
h1, h2, h3, h4,
outStr = "";
for (var i = 0; i < len;) {
h1 = commonbase64EncodeChars.indexOf(str.charAt(i++));
h2 = commonbase64EncodeChars.indexOf(str.charAt(i++));
h3 = commonbase64EncodeChars.indexOf(str.charAt(i++));
h4 = commonbase64EncodeChars.indexOf(str.charAt(i++));
outStr += String.fromCharCode((h1 << 2) | (h2 >> 4));
if (h3) outStr += String.fromCharCode(((h2 << 4) & 0xF0) | (h3 >> 2));
if (h4) outStr += String.fromCharCode(((h3 << 6) & 0xC0) | h4);
}
return outStr;
}
function filterBase64(str) {
var len = str.length,
c,
outStr = "";
for (var i = 0; i < len; i++) {
c = str.charAt(i);
if (commonbase64EncodeChars.indexOf(c) != -1) {
outStr += c;
}
}
return outStr;
}
document.querySelector("#input").addEventListener("input", function () {
var inputStr = this.value;
var encodeBase64Str = encodeBase64(unescape(encodeURI(inputStr)));
var decodeBase64Str = decodeURI(escape(decodeBase64(encodeBase64Str)));
document.querySelector("#enBase64").innerText = encodeBase64Str;
document.querySelector("#deBase64").innerText = decodeBase64Str;
})
</script>
</body>
</html>