原来浏览器原生支持JS Base64编码解码

转载来源:https://www.zhangxinxu.com/wordpress/2018/08/js-base64-atob-btoa-encode-decode/

一、基础不牢,选型糟糕

糟糕的技术选型往往源自自身技术广度不足。

就在数月前,一个前端HTML字符信息转Base64的需求,我是毫不犹豫去找了个开源的base64.js。

使用很简单,浏览器引入该JS文件,然后Base64编码这样:

Base64.encode('zhangxinxu');
// 返回:'emhhbmd4aW54dQ=='

解码就调用decode方法,如下:

Base64.decode('emhhbmd4aW54dQ==');
// 返回:'zhangxinxu'

数据准确,功能良好。当时弄完还洋洋得意,以为是个完美的解决。

结果,今天发现,尼玛原来浏览器很早就支持了JS Base64加密解密,而上面这种洋洋得意的做法完全就是瞎子点灯——白费蜡!根本就不是一个好的技术选型。

由于技术广度掌握不足,或者说JS基础掌握不牢,导致浪费了大把时间去找Base64的JS语言库,学习其API用法,换来一个冗余完全不需要加载的JS,现在来看,真是个糟糕的技术选型。

二、原生atob和btoa方法

实际上,从IE10+浏览器开始,所有浏览器就原生提供了Base64编码解码方法,不仅可以用于浏览器环境,Service Worker环境也可以使用。

方法名就是atobbtoa,具体语法如下:

1. Base64解码

语法为(浏览器中):

var decodedData = window.atob(encodedData);

或者(浏览器或js Worker线程中):

var decodedData = self.atob(encodedData);

例如:

window.atob('emhhbmd4aW54dQ==');
// 返回:'zhangxinxu'

眼见为实,您可以狠狠地点击这里:window.atob解码Base64字符demo

结果如下图:

记住atob
atob这个方法名称乍一看,很奇怪,不知道这个单词什么意思。我们可以理解为 A to B,也就是从A到B。这里的B指的就是Base64吗?哈哈哈,恭喜你!猜错了!A指的才是Base64,反的,B才是普通字符,普通意思就是low,俗称low B。所以我们这么记忆,Low B,Low B,B表示很Low的普通字符,A才是Base64,和首字母对应关系是反的。

因此,atob表示Base64字符to普通字符,也就是Base64解码。

2. Base64编码

语法为(浏览器中):

var encodedData = window.btoa(stringToEncode);

或者(浏览器或js Worker线程中):

var encodedData = self.btoa(stringToEncode);

例如:

window.btoa('zhangxinxu');
// 返回:'emhhbmd4aW54dQ=='

眼见为实,您可以狠狠地点击这里:window.btoa编码字符为Base64 demo

结果如下图:

记住btoa方法
btoa这个方法名称乍一看,很奇怪,不知道这个单词什么意思。我们可以理解为 B to A,也就是从B到A。那B指什么,A指什么呢?和atob方法一样,B指的是low B普通字符串,A指的是Base64字符。

因此,btoa方法表示low B普通字符to Base64字符,也就是Base64编码。

补充于2018-08-09
有人提到中文Base64数据转换会有报错问题。

错误如下:

The string to be encoded contains characters outside of the Latin1 range

雾霜月同学提出了解决方法,就是中文先encode转码和decode编码:

window.btoa(window.encodeURIComponent('嘻嘻哈哈哈哈啦啦啦啦'));
window.decodeURIComponent(window.atob('JUU1JTk4JUJCJUU1JTk4JUJCJUU1JTkzJTg4JUU1JTkzJTg4JUU1JTkzJTg4JUU1JTkzJTg4JUU1JTk1JUE2JUU1JTk1JUE2JUU1JTk1JUE2JUU1JTk1JUE2'));

我自己搜索了下,可以试试下面这样:

btoa(unescape(encodeURIComponent(str)))

我用SVG代码测试是OK的。

三、IE8/IE9的polyfill

当下,仍有不少PC项目还需要兼容IE9,所以,我们可以专门针对这些浏览器再引入一段ployfill脚本或者一个JS文件即可。

ployfill JS脚本戳这里,或者直接右键这里下载源文件!

实际使用,我们可以借助IE条件注释无缝对接。

也就是HTML中嵌入下面一段代码:

<!--[if IE]>
<script src="./base64-polyfill.js"></script>
<![endif]-->

[if IE]表示所有IE浏览器,由于IE10+浏览器已经放弃了著名的IE条件注释的支持,Chrome等浏览器本身就不支持这个IE私有语法,因此,很天然的,上面一段script引入只在IE9-浏览器下有效。而我们本来就希望只IE8,IE9浏览器引入ployfill,于是正好完美衔接上。

也就是原生支持atob和btoa方法的浏览器认为就是一段无需关心的HTML注释,不支持atob和btoa的IE9及其以下浏览器则会加载我们的base64-polyfill.js,使浏览器也支持window.btoawindow.atob这个语法。

眼见为实,您可以狠狠地点击这里:btoa/atob Base64编码解码polyfill demo

在Chrome浏览器下,可以看到没有polyfill相关JS的加载:

而IE8原生不支持atob和btoa方法的浏览器也正常编码解码Base64字符了,如下截图:

四、任意文件Base64编码

借助FileReader对象和readAsDataURL方法,我们可以把任意的文件转换为Base64 Data-URI。假设我们的文件对象是file,则转换的JavaScript代码如下:

var reader = new FileReader();
reader.onload = function(e) {// e.target.result就是该文件的完整Base64 Data-URI
};
reader.readAsDataURL(file);

基于此原理,我特意做了个简易小工具,可以得到任意文件的Base64 Data-URI,工具戳这里:base64.html

把对应的文件拖到工具页面任意位置即可。

例如一个只有’zhangxinxu’字符内容的txt文本拖进去可以得到:

可以看到文件的MIME type也自动识别出来了。然后base64,后面的关键内容数据会发现和执行btoa('zhangxinxu')结果一模一样,都是'emhhbmd4aW54dQ==',肯定必须要一样,不然我反而会怀疑自己哪里是不是弄错了。

此工具我用得很频繁,SVG转Base64,小尺寸图片转Base64,Woff字体转Base64,都是文件往里面一拖就搞定了,简单快捷。

此工具也是IE10+支持。

五、结束语

这两天看到一个新闻,说今年北半球很热:

近日,持续极端高温天气袭击整个北半球。瑞典北部北极圈内的温度一度达到30℃,10余起由高温导致的森林大火烧入北极圈;西伯利亚北部地区,气温也在本月初一度达到32℃,而往年同期,这一地区的平均温度只有10℃;日本继暴雨袭击后又迎热浪考验,高温致死案例频发;欧洲航天局近日公布卫星图片,丹麦西兰岛一处农田去年7月时还是遍地绿色,如今已呈“烤焦”的棕黄色……

加上看到不少人说今年东北很热,东北水库都干了,我就意识到,美的和格力的股票可以买起来了,2季度,3季度财报肯定会很好,因为天一热,买空调的人就会多。


最后,再分享个有技术含量的关于Low B的冷笑话——

一只小蜜蜂啊,飞到花丛中啊,飞呀飞呀,越来越高呀,然后对着下面小蜜蜂说了句:你个low bee!【捂脸】

/*** @description base64编码方法* @param val 需要编码的字符串* @return 返回编码好的base64字符串*   中文进行编码时,需要使用base64Encode(encodeURIComponent(a))*/
function base64Encode(val){var base64hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';val=encodeURIComponent(val);//把字符串转换为字符数组var strArr = val.split('');//装入结果的数组var result = [];//每个字符的ascii码var asciiCode;//上一个字符的ascii码var prevAsciiCode;var mod;//未填充之前的数组与3的模var preMod = strArr.length % 3;//使字符数组组成三个一组if(preMod == 1){strArr.push(null);strArr.push(null);}if(preMod == 2) strArr.push(null);//遍历整个数组,寻找每个字符的ascii码for(var index in strArr){if(!strArr[index]){asciiCode = 0;}else{asciiCode = strArr[index].charCodeAt();}//位于一组当中的第几个字符mod = index % 3;switch(mod){case 0://往右移2位result.push(base64hash[asciiCode >> 2]);break;case 1://上一个ascii码往左移4位与现在的ascii码往右移四位做或操作result.push(base64hash[(prevAsciiCode & 3) << 4 | asciiCode >> 4]);break;case 2://假设当前组的ascii为:01000111,00000011,00000000//2表示当前索引位于第三个,第二个ascii码和15相与,获得低四位的值,右移两位后再从第三个ascii获取高二位作为新6位数的低二位result.push(base64hash[(prevAsciiCode & 15) << 2 | asciiCode >> 6]);//与2的6次方减1相与,获得低6位的值result.push(base64hash[asciiCode & 63]);break}prevAsciiCode = asciiCode}//处理异常if(preMod == 1) {result.splice(result.length - 2,2);result.push('==');}else if(preMod == 2) {result.pop();result.push('=');}return result.join('');
}
/*** Base64译码* @param val base编码后的字符串* @returns {string} 原字符串*/
function base64Decode(val){var base64hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';//把字符串转换为字符数组var strArr = val.split('');//装入结果的数组var result = [];var preCode;var code;//余数,1-3var n;for(var i in strArr){n=i%4;code=base64hash.indexOf(strArr[i]);switch(n){case 0:preCode=base64hash.indexOf(strArr[i]);break;case 1:result.push(String.fromCharCode(preCode<<2|(code&48)>>4));break;case 2:result.push(String.fromCharCode((preCode&15)<<4 |(code&60)>>2));break;case 3:result.push(String.fromCharCode(((preCode&3)<<6)|code));break; }preCode=code;}return decodeURIComponent(result.join(''));
}

原来浏览器原生支持JS Base64编码解码相关推荐

  1. js base64 编码解码

    js base64 编码解码 encode decode,可以直接使用 function Base64() {// private property_keyStr = "ABCDEFGHIJ ...

  2. js base64编码解码 btoa atob 函数简介

    window.atob(string):解码 用来解码一个已经被base-64编码过的字符串.(参数string: 必需是一个通过 btoa() 方法编码的字符串) window.btoa(strin ...

  3. JS base64编码解码实战

    应用场景: 今天开发的时候像后端发起GET请求,参数只要一个code,code要类似这样子的: code=jsapi_ticket=JCNlm2qSQ_O4W7M7fK5jZBng3qgYNIMv3R ...

  4. js实现Base64编码解码

    js实现标准的Base64编码解码 Base64 是使用64个可打印ASCII字符(A-Z.a-z.0-9.+./)将任意字节序列数据编码成ASCII字符串,另有"="符号用作后缀 ...

  5. JS 浏览器中 文件转 base64 编码,生成 base64 代码

    JS 浏览器中 文件转 base64 编码,生成 base64 代码 JS 中将文件转 base 64 只需要 FileReader 的 readAsDataURL(文件) 方法即可 let file ...

  6. python实现base64解码_Python实现base64编码解码

    Python实现base64编码解码 通过编程了解base64编码解码过程 (纯属无聊之举,且不支持汉字) a = input("输入(1.base64加密/2.base64解密):&quo ...

  7. Golang Base64编码解码

    Golang Base64编码解码 Golang内置支持Base64编码解码,Go的encoding/base64包遵照RFC 4648规范实现了base64编码解码功能,包括标准方式以及URL/文件 ...

  8. Base64编码/解码VB6超精简版(适用于中、英文)

    上次因为要编写自动登录邮箱的程序,需要Base64编码,但是我看了几种版本的VB下Base64编码的程序,发现要么就是太冗长,要么就是不支持中文,要么根本不能用,于是我想求人不如求己,便仔细研究了一下 ...

  9. python使用base64编码解码数据

    python使用base64编码解码数据 base64模块是用来作base64编码解码,常用于小型数据的传输.编码后的数据是一个字符串,其包括a-z.A-Z.0-9./.+共64个字符,即可用6个字节 ...

最新文章

  1. AlphaGo、人工智能、深度学习解读以及应用
  2. Vue.js 打造酷炫的可视化数据大屏
  3. linux镜像文件不要大于4g,Systemback制做大于4G的Ubuntu系统镜像
  4. Vue系列vue-router的参数传递的两种方式(五)
  5. Redis zset(ziplist,skiplist)内部实现
  6. Cocos Creator 获取当前URL取参数
  7. WCDMA中的基本概念
  8. (笔记)《游戏脚本高级编程》——第1章 脚本编程概论
  9. python淘宝抢购脚本_Python 实现毫秒级淘宝、京东、天猫等秒杀抢购脚本
  10. 潘多拉固件设置ipv6_OpenWRT IPv6配置
  11. redis 的过期策略都有哪些?内存淘汰机制都有哪些?
  12. PDF文件拆分为图片
  13. Github项目:AI消除马赛克实战
  14. 如何判断channel是否已经关闭
  15. 船用炉灶的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  16. 技术干货:Linux Shell 编程基础,看这一篇就够了!
  17. 生活常用的塑料材质1到7
  18. word文档除号怎么打出来之除号插入的方法教程
  19. 最小的k个数(堆排序实现)
  20. [持续更新]大数据岗位实习日志

热门文章

  1. 网盘工具比较,以及自己开发的网盘工具[转]
  2. Hashtable Dictionary的使用
  3. 通过PPA升级你的LibreOffice
  4. PNG图在IE6下透明的终极解决方案
  5. linux chcon命令详解
  6. 用户空间与内核空间数据交换的方式------seq_file
  7. QuickSort 优化后的快速排序算法
  8. LeetCode 26. Remove Duplicates from Sorted Array
  9. Linux unzip命令:解压zip文件
  10. 【数字图像处理】一种求图像边缘的方法