window.btoa 和 window.atob,是浏览器提供的字符串 base64 编解码。
然而该办法不反对中文字符串的转码。因为转码是针对 ASCII 码。
能够如下操作实现
window.btoa(window.encodeURIComponent(str))
window.decodeURIComponent(window.atob(str))
先将中文编码,而后再转 base64
留神
无论是 escape,encodeURIComponent,encodeURI 那种办法,都不是专门针对中文的。
所以,以上办法也会将一些特殊符号 @*/+ 等转码
后果就是除了中文以外的其余字符最终后果和间接 btoa 的后果不统一。
这里就要看应用场景,只是前端应用没有问题,如果波及到后盾等第三方就不能用了。
罕用的 js-base 插件办法:encode,
原理如下
-
将字符串中非 acsill 字符按固定规定转为两个或者三个长度的 UTF-16 码
- 要害就是这段代码
const cb_utob = (c) => {if (c.length < 2) {var cc = c.charCodeAt(0); return cc < 0x80 ? c : cc < 0x800 ? (_fromCC(0xc0 | (cc >>> 6)) + _fromCC(0x80 | (cc & 0x3f))) : (_fromCC(0xe0 | ((cc >>> 12) & 0x0f)) + _fromCC(0x80 | ((cc >>> 6) & 0x3f)) + _fromCC(0x80 | (cc & 0x3f))); } else { var cc = 0x10000 + (c.charCodeAt(0) - 0xD800) * 0x400 + (c.charCodeAt(1) - 0xDC00); return (_fromCC(0xf0 | ((cc >>> 18) & 0x07)) + _fromCC(0x80 | ((cc >>> 12) & 0x3f)) + _fromCC(0x80 | ((cc >>> 6) & 0x3f)) + _fromCC(0x80 | (cc & 0x3f))); } }; const re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g; //utf-8 string return utf-16 字符串 const utob = (u) => u.replace(re_utob, cb_utob);
- 而后就能够转 base64 了
const btoaPolyfill = (bin) => {// console.log('polyfilled');
let u32, c0, c1, c2, asc = '';
const pad = bin.length % 3;
for (let i = 0; i < bin.length;) {if ((c0 = bin.charCodeAt(i++)) > 255 ||
(c1 = bin.charCodeAt(i++)) > 255 ||
(c2 = bin.charCodeAt(i++)) > 255)
throw new TypeError('invalid character found');
u32 = (c0 << 16) | (c1 << 8) | c2;
asc += b64chs[u32 >> 18 & 63]
+ b64chs[u32 >> 12 & 63]
+ b64chs[u32 >> 6 & 63]
+ b64chs[u32 & 63];
}
return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc;
};
- 这个办法是插件本人的转 base64 办法,每个 base64 字符代表 3 个 bit, 办法其实我没太看懂
mdn 还有另一种办法
- 原理字符串间接映射 ArrayBuffer 二进制数组
代码和地址如下:
/* Array of bytes to base64 string decoding */
function b64ToUint6 (nChr) {
return nChr > 64 && nChr < 91 ?
nChr - 65
: nChr > 96 && nChr < 123 ?
nChr - 71
: nChr > 47 && nChr < 58 ?
nChr + 4
: nChr === 43 ?
62
: nChr === 47 ?
63
:
0;
}
function base64DecToArr (sBase64, nBlockSize) {
var
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
nOutLen = nBlockSize ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockSize) * nBlockSize : nInLen * 3 + 1 >>> 2, aBytes = new Uint8Array(nOutLen);
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
nMod4 = nInIdx & 3;
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
if (nMod4 === 3 || nInLen - nInIdx === 1) {for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
}
nUint24 = 0;
}
}
return aBytes;
}
/* Base64 string to array encoding */
function uint6ToB64 (nUint6) {
return nUint6 < 26 ?
nUint6 + 65
: nUint6 < 52 ?
nUint6 + 71
: nUint6 < 62 ?
nUint6 - 4
: nUint6 === 62 ?
43
: nUint6 === 63 ?
47
:
65;
}
function base64EncArr (aBytes) {var eqLen = (3 - (aBytes.length % 3)) % 3, sB64Enc = "";
for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
nMod3 = nIdx % 3;
/* Uncomment the following line in order to split the output in lines 76-character long: */
/*
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) {sB64Enc += "\r\n";}
*/
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
if (nMod3 === 2 || aBytes.length - nIdx === 1) {sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));
nUint24 = 0;
}
}
return eqLen === 0 ?
sB64Enc
:
sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? "=" : "==");
}
MDN-base64