原生js实现base64编码方法

更新日期: 2019-09-06阅读: 2k标签: base64

常见对base64的认知(不完全正确)

首先对base64常见的认知,也是须知的必须有以下几点*

base64是一种图片编码方式,用一长串超长的字符串表示图片

在加载的时候会直接以字符串的形式加载出来,减少了图片加载的http请求

正常加载服务器静态资源的时候都应该是通过http请求回来,每加载一张图片时需要发起一次http请求 ,http请求建立需要一定的时间,所以对于小图而且出现频次比较高的话,这样的成本消耗其实是特别浪费的

所以一般base64编码适用于小图片,出现频次比较高的情况

当然base64编码也有一定的缺点

会增加图片本上的大小,对于小图来说,转码增加的大小和http请求发起的浪费时间相比还是划算的,但是对于大图和出现次数比较少的情况,这种方法就有待商榷

当然上面我现在项目这种问题就很不合适,肯定需要寻求一个好的方式来解决掉这个问题


多问一个为什么,base64到底是个啥?

base64是一种编码方式,将二进制编码为64字符串组成的字符码

标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。

为解决此问题,可采用一种用于URL的改进Base64编码,它在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。

另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。

此外还有一些变种,它们将“+/”改为“-”或“.”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(38 = 46 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

ok,我承认以上都是百度出来了,接下来谈谈我自己的认识,哈哈

直接掏个例子吧,比如,原生js是自带base64的编码方法的

var b = Buffer.from('asdasds'); //buffer 是js里面专门存放二进制的缓存区,暂时理解创建一个二进制变量
var s = b.toString('base64');
console.log(s)
//  YXNkYXNkcw==


按照我们的思路实现一下

base64是针对二进制对象进行编码,所以我们要将字符转换为二进制码

base64 是用64个字符表示二进制,2的6次方 = 64,所以base64的字符其实是每6个二进制位为单位,但是一个字节是8bit,如果不满6的倍数要往 字节转换后的二进制编码后面补0,比如如果是两个个字符

'ac' =》 转换为二进制为:'0110 0001 0110 0010' =》

如果要将这两个字符进行base64编码,但是base64仅支持6位二进制转换为一个字符,

截取之后就是=》 011000 010110 0010

那最后面的4位二进制不够转码,所以会在后面默认补零

补码完成之后开始转码 从000000 到111111分别对应ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=64个字符中的一个

转码完成

转换字符为二进制数

function toBinary (str){
    let tempResult = [];
    let result = [];
    // 分割字符
    str.split('').forEach(element => {
        //转二进制
        let binaryElement = element.charCodeAt().toString(2)
        //由于js原生方法转二进制如果前面是0可能会不满8位,所以前面补0,转为8位的对应ascii码二进制
        binaryElement = binaryElement.length === 8 ? binaryElement : ('0' + binaryElement)  //不足8位的二进制码在前面补0
        tempResult.push(binaryElement);
    });
    let index = 0;
    // 不满3个字符往后面补满3个字符(3个字符(24个二进制位)是6和8的最小公倍数)
    while(tempResult.length % 3 != 0){
        tempResult.push('00000000')
    }
    console.log(tempResult.length)
    return tempResult.join('');
}
let binary = toBinary('asdasds');

那么就是第一步和第二步实现了

二进制转 base64字符串

//将字符串存为数组
let KEYCODE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(''); 

function toBase64 (binary){
    console.log(binary);
    let tempResult = [];
    let result = [];
    let index = 0;
    // 每6位切割二进制
    while(index+6 < binary.length){
        tempResult.push(binary.slice(index,index+6))
        index = index + 6 ;
    }
    //不满6位的前面补0
    console.log(binary.slice(index,index+6))
    tempResult.push(("000000" + binary.slice(index,index+6)).substr( -6 ));
    tempResult.forEach(element => {
        //将二进制转为数组下标
        let index = parseInt(element,2);
        //获取对应下标字符串
        result.push(index === 0 ? '=' : KEYCODE[index])
    });
    //字符串拼接
    return result.join('')
}
let a = toBase64(binary);
console.log(a);

//  YXNkYXNkcw==

到这里基本就实现了,结果跟原生的方法打印的是一样的

但是也存在一些问题和改进

对于中文字符和特殊字符的支持

javascript中的中文都是默认utf-16编码,但是网页中编码格式基本都是UTF-8,然而即便我们用UTF-8格式保存了html文件,但是其中的中文字符依然是以UTF-16的形式保存的。所以我们首先要将中文字符转化为utf-8,然后再转二进制,最后即可用上面的方法进行编码
代码如下:  

var utf16ToUtf8 = function (utf16Str) {
var utf8Arr = [];
var byteSize = 0;
var tempList = [];
for (var i = 0; i < utf16Str.length; i++) {
    //获取字符Unicode码值
    var code = utf16Str.charCodeAt(i);

    //如果码值是1个字节的范围,则直接写入
    if (code >= 0x00 && code <= 0x7f) {
        byteSize += 1;
        utf8Arr.push(code);

        //如果码值是2个字节以上的范围,则按规则进行填充补码转换
    } else if (code >= 0x80 && code <= 0x7ff) {
        byteSize += 2;
        utf8Arr.push((192 | (31 & (code >> 6))));
        utf8Arr.push((128 | (63 & code)))
    } else if ((code >= 0x800 && code <= 0xd7ff)
        || (code >= 0xe000 && code <= 0xffff)) {
        byteSize += 3;
        utf8Arr.push((224 | (15 & (code >> 12))));
        utf8Arr.push((128 | (63 & (code >> 6))));
        utf8Arr.push((128 | (63 & code)))
    } else if(code >= 0x10000 && code <= 0x10ffff ){
        byteSize += 4;
        utf8Arr.push((240 | (7 & (code >> 18))));
        utf8Arr.push((128 | (63 & (code >> 12))));
        utf8Arr.push((128 | (63 & (code >> 6))));
        utf8Arr.push((128 | (63 & code)))
    }
}
var toBin = (n) => {
if(n == 0) return '0';
    var res = '';  
    while(n != 0) {
        res = n % 2 + res
        n = parseInt(n / 2)
        }  
    return res;
}
utf8Arr.forEach(element => {
   tempList.push(toBin(element)) 
});
return tempList.join('')
}

如何对图片base64编码进行实现

图片的话,要用到canvas ,将图片转换为二进制流,然后再掉用上述的编码方法 

 

链接: https://www.fly63.com/article/detial/5724

javascript图片转换base64,以及如何将base64的数据转换成图片

这篇文章主要讲解通过原生js,将图片地址转换为base64格式后显示的方法,以及base64的图片数据如何转换为file文件并提交。

js实现字符串/base64的编码和解码

JavaScript对字符串/base64的编码和解码;Base64其实是一种简单的置换加密方式,但是BASE64的用处往往并不是为了防止信息泄露,而且为了方便传输,进过BASE64编码后的信息会比原始信息长,大概是4/3倍。

js原生Base64转码和解码函数btoa和atob的使用

javascript原生的api是支持,Base64的, window.btoa方法将普通字符串转为Base64字符串,window.atob将Base64字符串转为普通字符串,它们在现代浏览器中受到广泛的支持。

图片保存到本地_原生js实现base64图片下载

在项目开发过程中,经常会有图片导出的需求,原生js实现base64图片下载实现思路:需要创建a标签,然后把base64的图片转为为blob对象,再通过URL.createObjectURL方法复制给a标签的href属性,最后添加添加事件的方法。

利用PHP将图片转换成base64编码的实现方法

base64是当前网络上最为常见的传输8Bit字节代码的编码方式其中之一。base64主要不是加密,它主要的用途是把某些二进制数转成普通字符用于网络传输。由于这些二进制字符在传输协议中属于控制字符,不能直接传送,所以需要转换一下

原生 JS 的 Base64 转码

JavaScript 原生提供两个 Base64 相关的方法:btoa():任意值转为 Base64 编码,atob():Base64 编码转为原来的值。注意:这两个方法不适合非 ASCII 码的字符,会报错。

js base64的实现

base64是用规定的64种字符来表示任意二进制数据的一种编码格式,base64编码不提供加密,只是将一种形式的数据转化为另一种形式。Base64编码使用二进制表示,字符串的每一个字符由8个字节表示

Base64 编码与解码详解

Base64 是基于 64 个可打印字符 A-Z、a-z、0-9、+、/ 来表示二进制数据的表示方法,常用于数据在网络中的传输。本篇将分别介绍其编码、解码以及实际运用。

base64原理浅析

为什么图片转成Base64编码,就可以直接内联到HTML中显示呢?为什么Base64编码后,体积会增大1/3呢?如果你对此也有疑问的话,就往下一看究竟吧。

使用base64编码在页面嵌入图片

因为页面中插入一个图片都要写明图片的路径——相对路径或者绝对路径。而除了具体的网站图片的图片地址,如果是在自己电脑文件夹里的图片,当我们的HTML文件在别人电脑上打开的时候图片则由于地址不对或者没有将图片

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!