zoukankan      html  css  js  c++  java
  • javascript实现base64格式转码与解码

      最近碰到一个需求,后端返回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的技术小白
  • 相关阅读:
    SQL server 插入不同IP的数据库
    SQL Server中的循环例子(网摘)
    C#小型数据库只能查询
    vue.prototype和vue.use的区别和注意点
    Ajax+PHP简单入门教程
    smarty在windows下的安装
    docker安装mysql镜像和容器
    Linux导出未越狱Iphone10.3QQ聊天记录
    记一次Struts中文乱码
    Ubuntu设置服务开机启动
  • 原文地址:https://www.cnblogs.com/shanfeng1000/p/15081040.html
Copyright © 2011-2022 走看看