base-64作为常见的编码函数,在基本认证摘要认证以及一些HTTP扩展中得到了大量应用。在前端领域,也常常把图片转换为base-64编码在网络中传输。本文将详细介绍base64的原理及用js实现base64编码器的过程

原理

  Base-64编码可以将任意一组字节转换成较长的常见文本字符序列,从而可以合法地作为首部字段值。Base-64编码将用户输入二进制数据打包成一种安全格式,将其作为 HTTP首部字段的值 发送出去,而无须担心其中包含会破坏HTTP分析程序的冒号、换行符或二进制值

  Base-64编码是作为MIME多媒体电子邮件标准的一部分开发的,这样MIME就可以在不同的合法电子邮件网关之间传输富文本和任意的二进制数据了。Base-64编码与将二进制数据文本化表示的uuencode和BinHex标准在本质上很类似,但空间效率更高

【拆分】

  Base-64编码将一个8位字节序列拆散为6位的片段,并为每个6位的片段分配一个字符,这个字符是Base-64字母表中的64个字符之一。这64个输出字符都是很常见的,可以安全地放在HTTP首部字段中。这64个字符中包含大小写字母、数字、+和/,还使用了特殊字符=

下表Base-64的字母表

0   A   8    I   16   Q   24   Y   32   g   40   o   48   w   56   4
1 B 9 J 17 R 25 Z 33 h 41 p 49 x 57 5
2 C 10 K 18 S 26 a 34 i 42 q 50 y 58 6
3 D 11 L 19 T 27 b 35 j 43 r 51 z 59 7
4 E 12 M 20 U 28 c 36 k 44 s 52 0 60 8
5 F 13 N 21 V 29 d 37 l 45 t 53 1 61 9
6 G 14 O 22 W 30 e 38 m 46 u 54 2 62 +
7 H 15 P 23 X 31 f 39 n 47 v 55 3 63 /

  [注意]由于Base64编码用8位字符表示信息中的6个位,所以Base-64编码字符串大约比原始值扩大了 33%

【编码实现】

  下图是一个简单的Base-64编码实例。在这里,三个字符组成的输入值“Ow!”是Base-64编码的,得到的是4个字符的Base-64编码值“T3ch”。它是按以下方式工作的

  1、字符串“Ow!”被拆分成3个8位的字节(0x4F、0x77、0x21)

  2、这3个字节构成了一个24位的二进制值010011110111011100100001

  3、这些位被划分为一些6位的序列010011、110111、01110、100001

  4、每个6位值都表示了从0-63之间的一个数字,对应Base-64字母表中64个 字符之一。得到的Base-64编码字符串是个4字符的字符串“T3ch”,然后就可 以通过线路将这个字符串作为“安全的”8位字符传送出去,因为只用了一些 移植性最好的字符(字母、数字等)

【填充】

  Base-64编码收到一个8位字节序列,将这个二进制序列流划分成6位的块。二进制序列有时不能正好平均地分成6位的块,在这种情况下,就在序列末尾填充零位,使二进制序列的长度成为24的倍数(6和8的最小公倍数)

  对已填充的二进制串进行编码时,任何完全填充(不包含原始数据中的位)的6位组都由特殊的第65个符号“=”表示。如果6位组是部分填充的,就将填充位设置为0

  下表显示了一些填充实例

  初始输入字符串“a:a”为3字节(24位)。24是6和8的倍数,因此无需填充,得到的Base-64编码字符串为“YTph”

  然而,再增加一个字符,输入字符串会变成32位长。而6和8的下一个公倍数是48,因此要添加16位的填充码。填充的前4位是与数据位混合在一起的。得到的6位组01xxxx,会被当作010000、十进制中的16,或者Base-64编码的Q来处理。剩下的两个6位组都是填充码,用“=”表示

  [注意]Base-64编码的官方规范移步至此

应用

  网页上的每一个图片,都需要消耗一个http请求下载而来的。所以,才有了雪碧图技术

  无论如何,图片的下载始终都要向服务器发出请求,要是图片的下载不用向服务器发出请求,而可以随着HTML的下载同时下载到本地那就太好了,而base64正好能解决这个问题

  前面提到过Base-64编码字符串大约比原始值扩大了33%。所以,不是所有的图片使用base-64编码都合适

  但是,如果图片足够小且因为用处的特殊性(如需要平铺等)无法被制作成雪碧图,在整个网站的复用性很高且基本不会被更新。那么此时使用base64编码传输图片就可谓好钢用在刀刃上

  比如,一个只有50字节的2px*2px的背景图。将其转化成base64编码,只有100多个字符,相比一个http请求,这种转换无疑更值得推崇

  把要转化的图片直接拖入chrome中,使用控制台中的Source选项,可直接查看图片的base64编码

字符串编码

  对于字符串来说,在javaScript中,有2个函数分别用来处理解码编码base64字符串:atob()btoa()

  btoa()函数能够从二进制数据“字符串”创建一个base-64编码的ASCII字符串;相反地,atob()函数能够解码通过base-64编码的字符串数据btoa()函数从 String 对象中创建一个 base-64 编码ASCII 字符串,其中字符串中的每个字符都被视为一个 二进制数据字节。

console.log(btoa('abc'));//'YWJj'
console.log(atob('YWJj'));//'abc'

  [注意]IE9-浏览器不支持

  但是,以上方法有局限性,就是无法转换中文

Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

  这时,就需要使用编码方法,先转换为btoa()识别的字符,再进行base64编码,如可以使用encodeURI()方法

var str = btoa(encodeURI('小火柴'));
console.log(str);//JUU1JUIwJThGJUU3JTgxJUFCJUU2JTlGJUI0
console.log(decodeURI(atob(str)));//'小火柴'
<p style="margin:0">请在下面的框中输入要转换的字符</p>
<textarea id="ta" cols="30" rows="10"></textarea>
<button id="btn1">转换</button><button id="btn2">反向转换</button><br>
<p style="margin:0">转换后的字符如下:</p>
<textarea id="result" cols="30" rows="10" readonly></textarea>
<button id="sel">全选</button>
<button id="reset">清空</button>
<script>
reset.onclick = function(){history.go();}
btn1.onclick = function(){result.value = btoa(encodeURI(ta.value));}
btn2.onclick = function(){result.value = decodeURI(atob(ta.value));}
sel.onclick = function(){
result.focus();
result.select();
}
</script>

图片编码

  使用文件File API的readAsDataURL()方法,可以将文件以数据URI(进行Base64编码)形式保存在result属性中

//base64转换函数
function base64(file){
if(fileData.innerHTML){
fileData.innerHTML = '';
btn.style.display = 'none';
}
if(file){
if(/image/.test(file.type)){
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(){
fileData.innerHTML = reader.result;
}
}else{
alert("You must select a valid image file!");
}
}
}

  一般地,生成的Base64编码都比较长,可以增加一个全选代码的功能

reader.onload = function(){
fileData.innerHTML = reader.result;
btn.style.display = 'inline-block';
btn.onclick = function(){
fileData.focus();
fileData.select();
}
}

  可以使用文件File API选择图片文件

//点击事件替代
targetArea.onclick = function(){file1.click();}
//控件选中
file1.onchange = function(){
var file = file1.files[0];
base64(file);
}

  当然也可以使用原生拖拽,实现图片拖拽,在某个区域显示Base64编码的效果

targetArea.ondragenter = function(e){this.style.outline = "1px solid black";}
targetArea.ondragleave = function(e){this.style.outline = "";}
//拖拽选中
targetArea.ondrop = function(e){
e = e || event;
this.style.outline = "";
var file = e.dataTransfer.files[0];
base64(file);
}

  由于File API的兼容性限制,以下代码在IE9-浏览器中无法正常运行

<input id="file1" type="file" accept="image/gif,image/jpeg,image/jpg,image/png,image/x-icon"  style="display:none">
<div id="targetArea" style="display:inline-block;vertical-align:middle;height:100px;line-height:50px;width:210px;background:lightblue;">将图片文件拖放到该区域内<br>或者点击该区域选择本地文件</div>
<textarea id="fileData" style="vertical-align:middle;width:400px;height:200px;overflow:auto;word-wrap: break-word;"></textarea>
<button id="btn" style="display:none;position:absolute;margin:220px 0 0 -80px">全选代码</button>
<script>
//base64转换函数
function base64(file){
if(fileData.innerHTML){
fileData.innerHTML = '';
btn.style.display = 'none';
}
if(file){
if(/image/.test(file.type)){
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(){
fileData.innerHTML = reader.result;
btn.style.display = 'inline-block';
btn.onclick = function(){
fileData.focus();
fileData.select();
}
}
}else{
alert("You must select a valid image file!");
}
}
}
//点击事件替代
targetArea.onclick = function(){file1.click();}
//控件选中
file1.onchange = function(){
var file = file1.files[0];
base64(file);
}
//兼容事件处理程序
function addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,handler,false);
}else{
target.attachEvent('on'+type,function(event){
return handler.call(target,event);
});
}
}
//兼容阻止默认事件
function preventDefault(e){
e = e || event;
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
}
addEvent(document,'dragover',preventDefault);
addEvent(document,'drop',preventDefault);
addEvent(targetArea,'dragenter',preventDefault);
addEvent(targetArea,'dragover',preventDefault);
addEvent(targetArea,'dragleave',preventDefault);
addEvent(targetArea,'drop',preventDefault);
targetArea.ondragenter = function(e){this.style.outline = "1px solid black";}
targetArea.ondragleave = function(e){this.style.outline = "";}
//拖拽选中
targetArea.ondrop = function(e){
e = e || event;
this.style.outline = "";
var file = e.dataTransfer.files[0];
base64(file);
}
</script>

用js实现base64编码器的更多相关文章

  1. 用javascript实现base64编码器

    前面的话 base-64作为常见的编码函数,在基本认证.摘要认证以及一些HTTP扩展中得到了大量应用.在前端领域,也常常把图片转换为base-64编码在网络中传输.本文将详细介绍base64的原理及用 ...

  2. 用javascript实现base64编码器以及图片的base64编码

    前面的话 base-64作为常见的编码函数,在基本认证.摘要认证以及一些HTTP扩展中得到了大量应用.在前端领域,也常常把图片转换为base-64编码在网络中传输.本文将详细介绍base64的原理及用 ...

  3. JS实现base64加密解密

    JS实现base64加密解密 转载自http://blog.csdn.net/fengzheng0306/archive/2006/04/25/676055.aspx 方法一: <HTML> ...

  4. js 图片base64转file文件的两种方式

    js 图片base64转file文件的两种方式 https://blog.csdn.net/yin13037173186/article/details/83302628 //将base64转换为bl ...

  5. js的Base64编码与解码

    js的Base64编码与解码 pc和手机app项目中,经常需要将手机自带的表情图片转换特定的编码格式与后台进行交互. Base64其实是一种简单的置换加密方式,但是BASE64的用处往往并不是为了防止 ...

  6. mui开发app之js将base64转图片文件

    之前我已经做过一个利用cropper裁剪并且制作头像的功能.如何在mui app中实现相册或相机获取图片后裁剪做头像请看另一篇博客:mui开发app之cropper裁剪后上传头像的实现 但是当时裁剪后 ...

  7. vue项目中使用md5.js及base64.js

    一.在项目根目录下安装 npm install --save js-base64 npm install --save js-md5 二.在项目文件中引入 import md5 from 'js-md ...

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

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

  9. JS实现——Base64编码解码,带16进制显示

    在网上找了个JS实现的Base64编码转换,所以就想自己研究下,界面如下: 将代码以BASE64方式加密.解密 请输入要进行编码或解码的字符: 编码结果以ASCII码16进制显示 解码结果以ASCII ...

随机推荐

  1. T2960 全民健身【思维Dp,预处理,差分优化】

    Online Judge:YCJSOI Label:Dp,思维题,预处理,滚动优化 题目描述 乐乐现在掌管一个大公司,办公楼共有n层.为了增加员工的身体素质,他决定在每层楼都建立一个活动室,活动室分乒 ...

  2. 满血复活前的记录(持续更新ing)

    时隔一年重新开启算法竞赛征程. 该记录大多为老课件.已经做过的习题重做和已经看过的书本重看 7.21 下午到山大 娄晨耀basic_algorithm课件中的内容: 复习线性筛原理 复习差分 做完Co ...

  3. win7 删除多余启动项的方法

    win7已经没有像xp那么简单的boot.ini让我们修改了,取而代之的是bcdedit.现在就简单的说下bcdedit的常规应用吧.开始,运行,输入bcdedit /?可以看到帮助.简单的应用开始. ...

  4. 【BZOJ3944】Sum

    题面 Description Input 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 Output 一共T行,每行两个用空格分隔的数ans1, ...

  5. React报错:Laravel React-Router browserHistory 刷新子页面报错404

    举例:myblog.com/ 刷新没问题 myblog.com/add 刷新404 browserHistory报404,hashHistory却正常 原因是少路由.web.php添加路由 Route ...

  6. 深入浅出 Java Concurrency (29): 线程池 part 2 Executor 以及Executors[转]

    Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具.真正的线程池接口是ExecutorService. 下面这张图完整描述了线程 ...

  7. Django之模板语言(二)-----Filter

    1.其他常用的模板语言: 通过模板语言可以让前端页面显示数据,数据可以是基本数据类型,也可以是对象亦或者对象的列表,结合着模板中的for.if等配合使用. 要注意前端页面中,出现没有后端数据的情况,随 ...

  8. ElasticSearch入门之彼行我释(四)

    散仙在上篇文章中,介绍了关于ElasticSearch基本的增删改查的基本粒子,本篇呢,我们来学下稍微高级一点的知识: (1)如何在ElasticSearch中批量提交索引 ? (2)如何使用高级查询 ...

  9. Activiti的helloworld

    所有语言的第一个程序都叫helloworld,姑且也称这第一个activiti程序为helloworld. 一个工作流想要实现,必定有一个对应的部署文件,利用流程设计器设计一个简单的流程,请假-> ...

  10. Luogu P4932 浏览器(二进制)

    P4932 浏览器 题意 题目背景 __stdcall在用\(Edge\)玩\(slay\)的时候,鼠标会经常失灵,这让她十分痛苦,因此她决定也要让你们感受一下\(Edge\)制造的痛苦. 题目描述 ...