@( 对于前端工程师来说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 ,将图片转换为二进制流,然后再掉用上述的编码方法


下一次

  • 可以尝试图片的base64编码
  • 可以做解码过程

前端对base64编码的理解,原生js实现字符base64编码的更多相关文章

  1. js实现base64编码与解码(原生js)

    一直以来很多人使用到 JavaScript 进行 base64 编码解码时都是使用的 Base64.js,但事实上,浏览器很早就原生支持 base64 的编码与解码了 以前的方式 编码: <ja ...

  2. js Jquery字符UrlEncode 编码 C#(asp.net)解码 Server HttpUtility 区别 cookies存中文

    一.Js asp.net 交互Url编码解码 C#(asp.net)编码:HttpUtility.UrlEncode(url) Jquery解码:decodeURIComponent(url); Jq ...

  3. js压缩图片base64长度

    var myCanvas=$('.img-container > img').cropper('getCroppedCanvas'); (function (base64){ var image ...

  4. 使用原生JS进行字符串转对象

    字符串转对象 目的 工作中如果需要原生 JS 完成字符转对象的话可以通过 JSON.parse(str), 但是这个方法是ES5中才出现, 如果需要兼容低版本就需要其它方法 使用原生 JS 解决字符串 ...

  5. 原生JS实现轮播+学前端的感受(防止走火入魔)

    插件!插件!天天听到有人求这个插件,那个插件的,当然,用第三方插件可以大幅提高开发效率,但作为新手,我还是喜欢自己来实现,主要是我有时间! 今天我来给大家分享下用原生JS实现图片轮播的写法 前辈们可以 ...

  6. 前端跨域问题相关知识详解(原生js和jquery两种方法实现jsonp跨域)

    1.同源策略 同源策略(Same origin policy),它是由Netscape提出的一个著名的安全策略.同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正 ...

  7. 大前端技术系列:TWA技术+TensorFlow.js => 集成原生和AI功能的app

    大前端技术系列:TWA技术+TensorFlow.js => 集成原生和AI功能的app ( 本文内容为melodyWxy原作,git地址:https://github.com/melodyWx ...

  8. 原生js轮播以及setTimeout和setInterval的理解

    下面这个代码是从一个群下载下来的,为了帮助自己理解和学习现在贴出来,与初学者共勉. <!DOCTYPE html> <html> <head> <meta c ...

  9. php和js中,utf-8编码转成base64编码

    1.php下转化base64编码 php中,文本文件的编码决定了程序变量的编码,比如以下代码在不同编码的php文件中,展示的效果也是不一样的 <?php $word = '严'; echo ba ...

随机推荐

  1. 修改编码为utf8mb4 以支持emoji表情

    环境: 项目db的所有字符集都已经初始化为utf-8,如 status命令显示如下: Server characterset: utf8Db characterset: utf8Client char ...

  2. Spring3.x 升级至 Spring4.x 详解

    1 升级依赖包 1.1 Maven 项目 1.1.1 更新 spring 依赖版本 打开 pom.xml,把所有 spring3.x 的版本号更新为 spring4.x.建议使用属性配置,形如: &l ...

  3. CSS--使用CSS Grid(网格)布局

    .一 CSS Grid(网格布局)简介 CSS Grid 布局由两个核心组成部分是父元素和子元素,父元素 是实际的 grid(网格),子元素是 grid(网格) 内的内容.下面是一个父元素和六个子元素 ...

  4. 【leetcode】877. Stone Game

    题目如下: Alex and Lee play a game with piles of stones.  There are an even number of piles arranged in ...

  5. c++11 指针空值

    1. 引入nullptr的必要性: 典型的指针初始化是将其指向一个空的位置.比如: int* my_ptr = 0; int* my_ptr = NULL; 一般情况下,NULL是一个宏定义. #un ...

  6. Chronograf启动(Influxdb的管理平台)

    1.创建一个bat文件,文件内容如下 @echo off:: 开启chronograf服务,服务监听端口9084echo 开启chronograf服务chronograf.exe /port 9084 ...

  7. Cenos7下nginx+mysql+php环境的搭建

    首先更新系统软件 1 $ yum update 第一步:安装nginx 1.安装nginx源 1 $ yum localinstall http://nginx.org/packages/centos ...

  8. 前端通过axios和FormData实现文件上传功能遇到的坑

    使用element-ui中的upload上传组件,前端上传数据参数已经传过去了,但是后端 (java) 接不到数据 (null) [解决方案] html部分: <el-button type=& ...

  9. CSS动画之旋转魔方轮播

    很久没有回头来复习CSS方面的知识了, 正好又到了月底写文章的deadline......所以这次选择了详细巩固一下CSS3动画有关的知识点,因为之前只是用过一些属性并没有深究细节. 在我自己写完这篇 ...

  10. PHP-利用二叉堆实现TopK-算法

    介绍 在以往工作或者面试的时候常会碰到一个问题,如何实现海量TopN,就是在一个非常大的结果集里面快速找到最大的前10或前100个数,同时要保证内存和速度的效率,我们可能第一个想法就是利用排序,然后截 ...