Base64编码原理及应用
最近在做一个H5上传图片并压缩的项目,其过程主要是先将图片上传通过readAsDataURL获取上传图片base64编码,然后根据高宽比将图片画到canvas上实现压缩,在通过toDataURL获取压缩后的图片。点击可查看demo在该过程中用到base64编码,于是就想弄清楚base64编码原理,才有了这篇博客。
Base64编码的来历
为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。最好的方法就是在不改变传统协议的情况下,做一种扩展方案来支持二进制文件的传送。把不可打印的字符也能用可打印字符来表示,问题就解决了。Base64编码应运而生,Base64编码就是一种基于64个可打印字符来表示二进制数据的表示方法。
Base64编码过程
- 将每三个字节作为一组,一共是24个二进制位。
- 将这24个二进制位分为四组,每个组有6个二进制位。
- 在每组前面加两个00,扩展成32个二进制位,即四个字节。
- 根据下表,得到扩展后的每个字节的对应符号,这就是Base64的编码值。
Base64编码表
| key | char | key | char | key | char | key | char |
|---|---|---|---|---|---|---|---|
| 0 | A | 17 | R | 34 | i | 51 | z |
| 1 | B | 18 | S | 35 | j | 52 | 0 |
| 2 | C | 19 | T | 36 | k | 53 | 1 |
| 3 | D | 20 | U | 37 | l | 54 | 2 |
| 4 | E | 21 | V | 38 | m | 55 | 3 |
| 5 | F | 22 | W | 39 | n | 56 | 4 |
| 6 | G | 23 | X | 40 | o | 57 | 5 |
| 7 | H | 24 | Y | 41 | p | 58 | 6 |
| 8 | I | 25 | Z | 42 | q | 59 | 7 |
| 9 | J | 26 | a | 43 | r | 60 | 8 |
| 10 | K | 27 | b | 44 | s | 61 | 9 |
| 11 | L | 28 | c | 45 | t | 62 | + |
| 12 | M | 29 | d | 46 | u | 63 | / |
| 13 | N | 30 | e | 47 | v | ||
| 14 | O | 31 | f | 48 | w | ||
| 15 | P | 32 | g | 49 | x | ||
| 16 | Q | 33 | h | 50 | y |
字符长度为能被3整除时,比如Man
M a n
ASCII: 77 97 110
8bit字节: 01001101 01100001 01101110
6bit字节: 010011 010110 000101 101110
十进制: 19 22 5 46
对应编码: T W F u
- "M"、"a"、"n"的ASCII值分别是77、97、110,对应的二进制值是01001101、01100001、01101110,将它们连成一个24位的二进制字符串010011010110000101101110。
- 将这个24位的二进制字符串分成4组,每组6个二进制位:010011、010110、000101、101110。
- 在每组前面加两个00,扩展成32个二进制位,即四个字节:00010011、00010110、00000101、00101110。它们的十进制值分别是19、22、5、46。
- 根据上表,得到每个值对应Base64编码,即T、W、F、u。
字符串长度不能被3整除时,比如Lucy:
L u c y
ASCII: 76 117 99 121
8bit字节: 01001100 01110101 01100011 01111001 00000000 00000000
6bit字节: 010011 000111 010101 100011 011110 010000 000000 000000
十进制: 19 7 21 35 30 16 (补0) (补0)
对应编码: T H V j e Q = =
如果要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可以使用下面的方法进行处理:
先使用0字节值在末尾补足,使其能够被3整除,然后再进行Base64的编码。在编码后的Base64文本后加上一个或两个=号,代表补足的字节数。也就是说,当最后剩余一个八位字节(1个byte)时,最后一个6位的Base64字节块有四位是0值,最后附加上两个等号;如果最后剩余两个八位字节(2个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。
因为,Base64将三个字节转化成四个字节,因此Base64编码后的文本,会比原文本大出三分之一左右。
注意
Base64编码主要用在传输、存储、表示二进制领域,不能算得上加密,只是无法直接看到明文,不建议用base64编码用于加密。
中文有多种编码(比如:utf-8、gb2312、gbk等),不同编码对应Base64编码结果都不一样。
base64实现
在PHP中,有一对专门的函数用于Base64转换:base64_encode()用于编码、base64_decode()用于解码。
在Javascript中可使用window.btoa()用于编码,window.atob()用于解码。 兼容性可点击查看IE10及以上全部兼容
对于IE10以下可采用以下兼容方法
/**
* base64 encoding & decoding
* for fixing browsers which don't support Base64 | btoa |atob
*/
(function (win, undefined) {
var Base64 = function () {
var base64hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// btoa method
function _btoa(s) {
if (/([^\u0000-\u00ff])/.test(s)) { // 排除中文
throw new Error('INVALID_CHARACTER_ERR');
}
var i = 0,
prev,
ascii,
mod,
result = [];
while (i < s.length) {
ascii = s.charCodeAt(i);
mod = i % 3;
switch (mod) {
// 第一个6位只需要让8位二进制右移两位
case 0:
result.push(base64hash.charAt(ascii >> 2));
break;
//第二个6位 = 第一个8位的后两位 + 第二个8位的前4位
case 1:
result.push(base64hash.charAt((prev & 3) << 4 | (ascii >> 4)));
break;
//第三个6位 = 第二个8位的后4位 + 第三个8位的前2位
//第4个6位 = 第三个8位的后6位
case 2:
result.push(base64hash.charAt((prev & 0x0f) << 2 | (ascii >> 6)));
result.push(base64hash.charAt(ascii & 0x3f));
break;
}
prev = ascii;
i++;
}
// 循环结束后看mod, 为0 证明需补3个6位,第一个为最后一个8位的最后两位后面补4个0。另外两个6位对应的是异常的“=”;
// mod为1,证明还需补两个6位,一个是最后一个8位的后4位补两个0,另一个对应异常的“=”
if (mod == 0) {
result.push(base64hash.charAt((prev & 3) << 4));
result.push('==');
} else if (mod == 1) {
result.push(base64hash.charAt((prev & 0x0f) << 2));
result.push('=');
}
return result.join('');
}
// atob method
// 逆转encode的思路即可
function _atob(s) {
s = s.replace(/\s|=/g, '');
var cur,
prev,
mod,
i = 0,
result = [];
while (i < s.length) {
cur = base64hash.indexOf(s.charAt(i));
mod = i % 4;
switch (mod) {
case 0:
//TODO
break;
case 1:
result.push(String.fromCharCode(prev << 2 | cur >> 4));
break;
case 2:
result.push(String.fromCharCode((prev & 0x0f) << 4 | cur >> 2));
break;
case 3:
result.push(String.fromCharCode((prev & 3) << 6 | cur));
break;
}
prev = cur;
i++;
}
return result.join('');
}
return {
btoa: _btoa,
atob: _atob,
encode: _btoa,
decode: _atob
};
}();
if (!win.Base64) { win.Base64 = Base64 }
if (!win.btoa) { win.btoa = Base64.btoa }
if (!win.atob) { win.atob = Base64.atob }
})(window)
Base64实际运用
- 用base64引入图片,当图片大小较小时可直接将其用base64编码,这样可以减少请求,目前webpack中可使用url-loader处理图片
- 在邮件中使用base64编码
参考文章
Base64编码原理及应用的更多相关文章
- BASE64编码原理分析脚本实现及逆向案例
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理你又了解多少?今天小编带大家了解一下Base64编码原理分析脚本实现及逆向案例的相关内容. 01编码由来 数 ...
- Atitit.Base64编码原理与实现设计
Atitit.Base64编码原理与实现设计 1. Base64编码1 1.1. 为什么要用自己的base64编码方案1 2. Base64编码由来1 3. Base64编码原理1 3.1. 具体来说 ...
- Base64 编码原理
什么是 Base64 编码 Base64 编码是最常见的编码方式,基于 64 个可打印字符来表示任意二进制数据的方法,是从二进制转换到可见字符的过程. 使用场景 数据加密或签名通过 Base64 转换 ...
- Base64编码原理分析
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在了解Base64编码之前,先了解几个基本概念:位.字节. 位:"位(bit)"是计算机中最小的数据单位.每一位 ...
- Base64编码原理与应用
本文内容转自网络,如需详细内容,请参考相关网址. http://my.oschina.net/goal/blog/201032 代码参考:http://blog.csdn.net/prsniper/a ...
- 一篇文章彻底弄懂Base64编码原理
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...
- 一篇文章彻底弄懂Base64编码原理(转载)
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...
- 知识扩展——(转)一篇文章彻底弄懂Base64编码原理
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. 一.Base64的由来 目前Base64已经成 ...
- 一篇文章彻底搞懂base64编码原理
开始 在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇文章带领大家了解一下Base64的底层实现. base64是什么东东呢? Base64 ...
随机推荐
- Flex调用本地文件分析
最近在用Flex做一个相册的功能,因为图片数据很多,所以想调用本地文件的方式做. 但是B/S的缘故,很多安全上的限制给我造成了不小的麻烦,把我这个小菜鸟弄的晕头转向. 第一,刚开始,查了很多资料发现都 ...
- 20191010-9 alpha week 1/2 Scrum立会报告+燃尽图 07
此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/8752 一.小组情况 队名:扛把子 组长:迟俊文 组员:宋晓丽 梁梦瑶 韩昊 ...
- Selenium+Java(四)Selenium Xpath元素定位
前言 关于Selenium元素定位,这是最后一篇博客. Xpath定位可以实现的功能 Selenium+Java(三)Selenium元素定位中讲的定位方式也可以实现,具体要用那种定位方式要根据自己的 ...
- OAuth 2.0 概念及授权流程梳理
本文可以转载,但请注明出处https://www.cnblogs.com/hellxz/p/oauth2_process.html OAuth2 的概念 OAuth是一个关于授权的开放网络标准,OAu ...
- Java核心技术第八章-泛型
摘要 本文根据<Java核心技术 卷一>一书的第八章总结而成,部分文章摘抄书内,作为个人笔记. 文章不会过于深入,望读者参考便好. 为什么要使用泛型程序设计 泛型程序设计(Generic ...
- 替换节点(replaceChild())
replaceChild():方法将把一个给定父元素里面的一个子节点替换为另一个子节点: referencre = element.replaceChild(newChild,oldChild); o ...
- 如何优雅地在Stack Overflow提问?
今天来给大家聊一聊 Stack Overflow,Stack Overflow 是什么呢? 什么是 Stack Overflow? Stack Overflow 是一个全球最大的技术问答网站,作为一个 ...
- 【前端】之HTML5基础知识
HTML5 文件格式 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- vsftpd架设(配置pam模块)
Vsftpd 是很安全的ftp软件 VSFTPD的目录结构 /usr/sbin/vsftpd: VSFTPD的可执行文件 /etc/rc.d/init.d/vsftpd:启动脚本 /etc/vsftp ...
- javascript获取当前时间CurentTime
function CurentTime(){ var now = new Date(); var year = now.getFullYear(); //年 var month = now.getMo ...