【算法】base64与Uin8Array互转实现

本文详细介绍了如何使用Node.js实现Base64编码,用于ASCII字符转换和HTTP/MIME协议下的数据传输,重点在于确保数据正确性,而非加密。通过实例展示了编码和解码的过程,并指出其在非ASCII环境下传输的优势。
摘要由CSDN通过智能技术生成

base64格式协议rfc2045-2049

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())

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值