base64实质上是把3byte的转成4byte的字符串
是为了方便把二进制转成字符串进行传输避免不同平台上的差异
虽然toString也是可以实现base64的,但还是需要弄懂其原理
下面是我用nodejs实现的
base64不是加密解密算法。能起到安全作用的效果很差,而且很容易破解,他核心作用应该是传输数据的正确性,有些网关或系统只能使用ASCII字符。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法,而且base64特别适合在http,mime协议下快速传输数据
let base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
class Base64Helper {
instance = new Base64Helper();
constructor() { }
// buf转base64(3变4)
static bufToBase64(buf) {
let encoded_str = '';
let mod = buf.length % 3;
let sum = Math.floor(buf.length / 3);
// console.log(mod, sum, buf.length)
for (let i = 0; i < sum * 3; i += 3) {
let idx1, idx2, idx3;
idx1 = i;
idx2 = i + 1;
idx3 = i + 2;
let byte1, byte2, byte3, byte4;
// 拿走1前6位
byte1 = buf[idx1] >> 2;
// 拿走1后两位和2的前4位
byte2 = ((buf[idx1] & 0x03) << 4) | ((buf[idx2]) >> 4);
// 拿走2的后四位和3的前两位
byte3 = ((buf[idx2] & 0xf) << 2) | (buf[idx3]) >> 6;
// 拿走3的后6位
byte4 = (buf[idx3] & 0x3f);
encoded_str += base[byte1] + base[byte2] + base[byte3] + base[byte4];
}
if (mod == 1) {
let byte1, byte2, byte3, byte4;
// 拿走1前6位
byte1 = buf[buf.length - 1] >> 2;
// 拿走1后两位和2的前4位
byte2 = (buf[buf.length - 1] & 0x03) << 4;
encoded_str += base[byte1] + base[byte2] + '=' + '=';
} else if (mod == 2) {
let byte1, byte2, byte3, byte4;
// 拿走1前6位
byte1 = buf[buf.length - 2] >> 2;
// 拿走1后两位和2的前4位
byte2 = ((buf[buf.length - 2] & 0x03) << 4) | ((buf[buf.length - 1]) >> 4);
// 拿走2的后四位和3的前两位
byte3 = ((buf[buf.length - 1] & 0x0f) << 2);
encoded_str += base[byte1] + base[byte2] + base[byte3] + '=';
}
return encoded_str
}
// base64转buffer(4变3)
static base64ToBuf(base64Data) {
// base64Data.
let equalCount = base64Data.match(/=/g) || 0;
base64Data = base64Data.replace(/=/g, '');
let len = base64Data.length;
let mod = len % 4;
let sum = Math.floor(len / 4);
let idx = 0;
let moreLen = 0;
if (equalCount && equalCount.length == 1) moreLen = 2;
if (equalCount && equalCount.length == 2) moreLen = 1;
let buf = new Uint8Array(sum * 3 + moreLen);
for (let i = 0; i < sum * 4; i += 4) {
let char0 = base64Data[i];
let char1 = base64Data[i + 1];
let char2 = base64Data[i + 2];
let char3 = base64Data[i + 3];
let charIdx0 = base.indexOf(char0);
let charIdx1 = base.indexOf(char1);
let charIdx2 = base.indexOf(char2);
let charIdx3 = base.indexOf(char3);
if (charIdx0 == -1 || charIdx1 == -1 || charIdx2 == -1 || charIdx3 == -1) {
continue;
}
// byte1 =
// 后6 前2
buf[idx++] = (charIdx0 << 2) | (charIdx1 >> 4 & 0x03);
buf[idx++] = (charIdx1 << 4) | (charIdx2 >> 2 & 0x0f);
buf[idx++] = (charIdx2 << 6) | (charIdx3 & 0x3f);
}
if (equalCount && equalCount.length > 0) {
if (equalCount.length == 1) {
let charIdx0 = base.indexOf(base64Data[base64Data.length - 3]);
let charIdx1 = base.indexOf(base64Data[base64Data.length - 2]);
let charIdx2 = base.indexOf(base64Data[base64Data.length - 1]);
// 一个等号说明有三位码,18bit(实16bit) 可以合成2位
buf[buf.length - 2] = (charIdx0 << 2) | (charIdx1 >> 4);
buf[buf.length - 1] = (charIdx1 << 4) | (charIdx2 >> 2);
} else if (equalCount.length == 2) {
// 一个等号说明有二位码,可以合成1位
let charIdx0 = base.indexOf(base64Data[base64Data.length - 2]);
let charIdx1 = base.indexOf(base64Data[base64Data.length - 1]);
buf[buf.length - 1] = (charIdx0 << 2) | (charIdx1 >> 4);
}
}
return Buffer.from(buf);
}
static convertStringToBase64(str) {
let utf8Bytes = new TextEncoder().encode(str)
let base64String = Base64Helper.bufToBase64(utf8Bytes);
return base64String;
}
static convertBase64ToString(base64String) {
let decodedUtf8Bytes = Base64Helper.base64ToBuf(base64String);
let decodedString = new TextDecoder().decode(decodedUtf8Bytes);
return decodedString;
}
}
let buf;
let originalStr = "这串文字会转成base64,然后再转成buffer,转成string显示出来。abcde";
buf = Buffer.from(originalStr)
let toStringRes = buf.toString('base64')
let base64HeplerRes = Base64Helper.bufToBase64(buf)
console.log('toString结果', toStringRes)
console.log('base64Hepler结果', base64HeplerRes)
console.log('还原文字', Base64Helper.base64ToBuf(base64HeplerRes).toString())