添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

这篇文章发布于 2018年08月4日,星期六,01:02,归类于 JS API 。 阅读 152483 次, 今日 3 次 49 条评论

一、基础不牢,选型糟糕

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

就在数月前,一个前端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环境也可以使用。

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

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.btoa window.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!【捂脸】

(本篇完)

周六凌晨1点多了,还在撸帖子,蛮拼的嘛!
不过再看到你不知道原生有base64支持,瞬间有一丁点优越感,哈哈!?

atob 意思:ascii to binary atob(“emhhbmd4aW54dQ==”) // “zhangxinxu”
btoa 意思:binary to ascii btoa(“zhangxinxu”) // “emhhbmd4aW54dQ==”

所以直接用中文转base64会报错

另外: 建议用escape处理中文,encodeURIComponent返回会比escape长

2019年01月1日 14:55

ECMAScript v3 已从标准中删除了 unescape() 函数,并反对使用它,因此应该用 decodeURI() 和 decodeURIComponent() 取而代之。

$mycode=StripStr(“你好我是 ‘www.baidu.com'”);
$base64show=base64_encode($mycode);

结果是 5L2g5aW95oiR5pivICYjMDM5O3d3dy5iYWlkdS5jb20mIzAzOTs=
转码还原单引号变成转义成 #039;
怎么得到不转义单引号的 base64字窜符

还有一个思路:
“的原型方法`toDataURL`支持将 canvas 里的内容转成 base64,可以将字符串用`fromCharCode`和位运算截断转换成 image data 格式的`Uint8ClampedArray`,放进 canvas 里再搞成 base64。
不过要注意浏览器会把带透明度的图片有损压缩,所以注意写 image data 的时候不要写到 alpha 值(即`下标&11===0`的那些数据)。

2018年08月20日 11:56

大佬, 向您请教个问题, 在有 contenteditable=”true” 的元素上, 或者表单元素上, focus时, 文字下方会有红色波浪号, 如何取消这个波浪号?

在我输入这段文字的时候就会出现这种情况.
This is a piece of wroooooooooooongly written character.
评论里无法发图, 这段文字复制到评论框就能看到我说的现象,

关于svg转base64,个人不建议转base64,采用svg+xml方式,代码比base64小,而且可以直观的改大小、颜色等。

原svg代码:

转换后(可用于img的src或作为背景图 background-image: url()使用):
“data:image/svg+xml,%3csvg xmlns=’http://www.w3.org/2000/svg’ width=’64’ height=’64’%3e %3cpath fill=’none’ stroke=’%23999′ stroke-width=’4′ stroke-linecap=’round’ d=’M11 32h42M33 52l20-20M33 13l20 19’/%3e %3c/svg%3e”

原svg代码:
<svg xmlns=”http://www.w3.org/2000/svg” width=”64″ height=”64″>
<path fill=”none” stroke=”#999″ stroke-width=”4″ stroke-linecap=”round” d=”M11 32h42M33 52l20-20M33 13l20 19″/>
</svg>

atob, btoa 的解释好奇怪。专门去mdn 看了下文档,这里做个记录。 a 是指 ASCII, b 是指 binary。

Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation

https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22

中文无法转码,会出现如下错误提示:

VM174:1 Uncaught DOMException: Failed to execute ‘btoa’ on ‘Window’: The string to be encoded contains characters outside of the Latin1 range.
at :1:9

中文需要转码
window.btoa(window.encodeURIComponent(‘嘻嘻哈哈哈哈啦啦啦啦’));
window.decodeURIComponent(window.atob(‘JUU1JTk4JUJCJUU1JTk4JUJCJUU1JTkzJTg4JUU1JTkzJTg4JUU1JTkzJTg4JUU1JTkzJTg4JUU1JTk1JUE2JUU1JTk1JUE2JUU1JTk1JUE2JUU1JTk1JUE2’));

mdn 关于unicode的处理方法:
function utf8_to_b64( str ) {
return window.btoa(unescape(encodeURIComponent( str )));

function b64_to_utf8( str ) {
return decodeURIComponent(escape(window.atob( str )));
2018年08月5日 22:36

如果都是你自己编码解码那倒无所谓了,但是大部分时候编码解码并不都是纯前端呀,有可能是后端或者是客户端编码过来的,难道你也要让对方先 url 编码一下么,不太合适吧。

Chrome 67内核, 转中文直接报错
VM340:1 Uncaught DOMException: Failed to execute ‘btoa’ on ‘Window’: The string to be encoded contains characters outside of the Latin1 range.

张鑫旭 ,09年 华中科技大学 毕业,现 上海 ,就职于 阅文集团 ,专注 web前端 偏前领域,著有 《CSS世界》 《CSS选择器世界》 《CSS新世界》

邮箱: zhangxinxu@zhangxinxu.com

关注我: 微信 微博 掘金 知乎 头条 B站 Gitee

  • 寥寥数行SVG实现圆环loading或倒计时效果 (37)
  • 小tip: 外链地址网站标志图标API应用 (16)
  • i, b, em, strong元素在HTML5中的新语义 (14)
  • jQuery页面滚动图片等元素动态加载实现 (14)
  • 了不起的IE7浏览器-CSS新特性-实现与思维变革 (14)
  • jQuery powerFloat万能浮动层下拉层插件 (12)
  • 趁热打铁,SVG feColorMatrix滤镜gogogo! (11)
  • 学习了,CSS中内联SVG图片有比Base64更好的形式 (9)
  • jQuery html5Validate基于HTML5表单验证插件 (8)
  • CSS深入理解vertical-align和line-height的基友关系 (8)
  • 今年热议

  •