• 周六. 7月 2nd, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

javascript实现base64格式转码与解码

admin

11月 28, 2021

  最近碰到一个需求,后端返回base64格式的数据,前端需要进行base64格式解码,好了,前端采用内部提供的atob函数进行解码,开完成,交付测试,然后测试小哥哥小姐姐反馈说中文乱码!

  然后查了一下,我后端代码采用utf8编码,这没问题,问题出在前端使用的atob函数,它居然采用的是Latin1(ISO-8859-1)编码!还不能修改编码方式,而且它还只在web端开发有这个atob函数!也不知道写这个atob函数的作者出于什么目的,Latin1(ISO-8859-1)编码用的很广么?竖中指!!!!

  没办法,问题要解决,我们本可以找一下第三方的包,但想想,还是觉的自己实现一个转码的函数,留着备用,这里分享出来:

    let base64util = function () {
        let _keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

        //base64格式加密
        function encode(input) {
            if (typeof input != "string") {
                input = JSON.stringify(input)
            }

            //utf8转码,Unicode值转换为字节数组
            let buffer = [];
            for (var n = 0; n < input.length; n++) {
                var c = input.charCodeAt(n);
                if (c < 128) {              //一个字节
                    buffer.push(c);
                } else if (c < 2048) {      //两个字节
                    buffer.push((c >> 6) | 192, (c & 63) | 128);
                } else if (c < 65536) {     //三个字节
                    buffer.push((c >> 12) | 224, ((c >> 6) & 63) | 128, (c & 63) | 128);
                } else if (c < 2097152) {   //四个字节
                    buffer.push((c >> 18) | 240, ((c >> 12) & 63) | 128, ((c >> 6) & 63) | 128, (c & 63) | 128);
                } else if (c < 67108864) {  //五个字节
                    buffer.push((c >> 24) | 248, ((c >> 18) & 63) | 128, ((c >> 12) & 63) | 128, ((c >> 6) & 63) | 128, (c & 63) | 128);
                } else {                    //六个字节
                    buffer.push((c >> 30) | 252, ((c >> 24) & 63) | 128, ((c >> 18) & 63) | 128, ((c >> 12) & 63) | 128, ((c >> 6) & 63) | 128, (c & 63) | 128);
                }
            }

            //转码,三字节转换成四字节
            let i = 0, padding = buffer.length % 3;
            padding && buffer.push(...new Array(padding = 3 - padding).fill(0));//先用0填补
            let result = []
            while (i < buffer.length) {
                let [c1, c2, c3] = [buffer[i++], buffer[i++], buffer[i++]];
                result.push(c1 >> 2, ((c1 & 0b11) << 4) | (c2 >> 4), ((c2 & 0b1111) << 2) | (c3 >> 6), c3 & 63);
            }
            padding && (result.splice(result.length - padding), result.push(...new Array(padding).fill(64)));//把0填补换成=
            return result.map(v => _keys.charAt(v)).join("");
        }
        //base64格式解码
        function decode(input) {
            if (typeof input != "string") {
                throw "invalid argument"
            }

            //解码,四字节转换成三字节
            let buffer = input.split(""), i = 0, padding;
            let r = []
            while (i < buffer.length) {
                let array = buffer.slice(i, i += 4).map(v => _keys.indexOf(v))
                if (array.length != 4 || array.some(v => v < 0)) throw "invalid input"
                padding = array.filter(v => v == 64).length;//获取填补的=号数量
                padding && (array.splice(r.length - padding), array.push(...new Array(padding).fill(0)));//把=填补换成0
                let [e1, e2, e3, e4] = array
                r.push((e1 << 2) | (e2 >> 4), ((e2 & 15) << 4) | (e3 >> 2), ((e3 & 3) << 6) | e4);
            }
            padding && r.splice(r.length - padding)//去掉填补

            //utf8转码,字节数组转换成Unicode值
            i = 0;
            buffer = [];
            while (i < r.length) {
                let c = r[i++]
                if (c < 128)        //一个字节
                    buffer.push(c);
                else if (c < 224)   //两个字节
                    buffer.push(((c & 31) << 6) | (r[i++] & 63));
                else if (c < 240)   //三个字节
                    buffer.push(((c & 15) << 12) | ((r[i++] & 63) << 6) | (r[i++] & 63));
                else if (c < 248)   //四个字节
                    buffer.push(((c & 7) << 18) | ((r[i++] & 63) << 12) | ((r[i++] & 63) << 6) | (r[i++] & 63));
                else if (c < 252)   //五个字节
                    buffer.push(((c & 3) << 24) | ((r[i++] & 63) << 18) | ((r[i++] & 63) << 12) | ((r[i++] & 63) << 6) | (r[i++] & 63));
                else                //六个字节
                    buffer.push(((c & 1) << 30) | ((r[i++] & 63) << 25) | ((r[i++] & 63) << 18) | ((r[i++] & 63) << 12) | ((r[i++] & 63) << 6) | (r[i++] & 63));
            }
            return buffer.map(v => String.fromCharCode(v)).join("");
        }

        return { encode, decode }; 
    }()

  使用:  

    //转码
    base64util.encode("say:上山打老虎")
    //解码
    base64util.decode("c2F5OuS4iuWxseaJk+iAgeiZjg==")

  结果:

  

一个专注于.NetCore的技术小白

发表评论

您的电子邮箱地址不会被公开。