data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...为什么可以显示图片- 我可以把图片放入
json中吗?
诞生的历史背景
SMTP协议(电子邮件传输协议)开始是基于纯ASCII文本的,也就导致非英语字符,二进制的附件(图片,文档等)都不能在电子邮件中使用,而如果有一种编码可以讲二进制转化为ASCII,那在邮件中就可以使用图片,文档啦。
base64编码
采用64位指定的字符A-Z a-z 0-9 + /实现二进制文件跟ASCII字符串的转换,不懂啥是ASCII的,二进制请戳 (从'𠮷'.length !== 1去理解js中的字符串编码)看看计算机基础章节
base64的编码规则详看阮老师的Base64笔记
注意:
Base64将三个字节转化成四个字节,因此Base64编码后的文本,会比原文本大出三分之一左右
JS原生API:atob和btoa方法
从IE10+浏览器开始,所有浏览器就原生提供了Base64编码解码方法
btoa("zhangsan") // 'emhhbmdzYW4='
atob('emhhbmdzYW4=') // zhangsan
⚠️注意:
之前也提到过, js中String类型及DOMString都是采用UTF-16编码的,如果有字符超出了8位ASCII编码的字符范围时,在大多数的浏览器中对Unicode字符串调用 window.btoa 将会造成一个 Character Out Of Range 的异常,比如调用btoa("中文"),解决方法有多种,
MDN里面介绍了四种方法解决Unicode转化base64的问题
应用场景
HTML中用DataURL内联小图片 减少HTTP请求
// 1. 直接使用img标签的src属性
<img alt="Embedded Image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA..." />
// 2. css的url参数
<style>
.bg {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...") no-repeat cetnter;
}
</style>
目前前端工程中,会把小于一定大小的文件用base64编码,dataUrl内联的方式来减少http请求。如:
- webpack5的默认会把小于8kb大小的文件进行base64编码后内联的方式,通过
Rule.parser.dataUrlCondition.maxSize可自定义配置 - create-react-app中默认会将小于10,000字节的bmp, gif, jpg, jpeg, png也会编码为base64,通过环境变量
IMAGE_INLINE_SIZE_LIMIT也可自定义配置
由于Base64将三个字节转化成四个字节,因此Base64编码后的文本,会比原文本大出三分之一左右,也就是会会明显增大HTML/CSS文件的大小,所以只应用于较小的图片,不然会影响加载速度。
在json中嵌入小附件
用户上传的图片或者其他二进制附件都可以选择通过base64编码,放进json中,然后传递给后台,比如以下用json传递一张小图片。
{
"icon": 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAARtJREFUOE+l0i0sxVEcxvHPDSQUBJuhmkIgKwSFCURsRqaYl+hlEpXZmMZmowgUmUAxFbMJKCgkO9s529/d/bt3c9J5eX7f/X7Pcwr+uQo59b24xUt8b0QHLor1xYAtTEVhgKzFgvnM3TamEygLOEQNBuJjO47jfgh3cX+KT4yEcwL04Qx1+ChjSy3e0Y/zBFhAW2y/ElvDGPdYTYAT7OOokmoMYwyDCbCOKsxWCNjEF+YSoBuX6MJNGUgnrtGDq2wKG9GHUXznQKpxEOefyaaQ9CHKBozjsQjSgj28pghLAcLdG54xEVqMkDDiLppQnwXnfeXgRysmo3gHD3HuX43lAYJoGYtRvYKlUr78BQj65lj0lJdMOUDZb/EDgXMwERd8NRMAAAAASUVORK5CYII='
}
sourcemap
在内联的sourcemap中,在文件的末端有这样一行注释
你写的代码.....
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJza...