前面的话

  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的字母表

   A       I      Q      Y      g      o      w     
B J R Z h p x
C K S a i q y
D L T b j r z
E M U c k s
F N V d l t
G O W e m u +
H P X f n v /

  [注意]由于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编码的字符串数据。

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>

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

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

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

  2. 用js实现base64编码器

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

  3. Javascript中Base64编码解码的使用实例

    Javascript为我们提供了一个简单的方法来实现字符串的Base64编码和解码,分别是window.btoa()函数和window.atob()函数. 1 var encodedStr = win ...

  4. javascript中base64和Gzip的使用

    一般的使用流程(4步): 服务器端将字符串Gzip压缩为 字节数组——>通过base64转为字符串(后传递到客户端)——>解码base64字符串为字节数组——>Gzip解码字节数组为 ...

  5. Javascript实现base64的加密解密【转】

    场景 这几天使用PHP向前端传值的时候,遇到一个问题,要将代码传过去赋值.如果使用urlencode()和urldecode()函数,就会出现js无法解码的情况,因为php和js的相关函数算法不一致. ...

  6. javascript实现base64编码、解码

    我们知道,浏览器的window对象提供有window.atob()和window.btoa()方法可以对字符串进行Base64编码和解码. console.log(window.btoa(window ...

  7. Javascript实现base64的加密解密

    //1.加密解密方法使用: //1.加密 var str = '124中文内容'; var base = new Base64(); var result = base.encode(str); // ...

  8. javascript将base64编码的图片数据转换为file并提交

    /** @param base64Codes 图片的base64编码 */ function sumitImageFile(base64Codes){ var form=document.forms[ ...

  9. (转载)javascript将base64编码的图片数据转换为file并提交

    /** * @param base64Codes * 图片的base64编码 */ function sumitImageFile(base64Codes){ var form=document.fo ...

随机推荐

  1. 与中国最顶尖sharepoint工程师共舞

    最近又跳了,来到某家外企.自以为善能称心如意,谁知乃井里之蛙. 给我的最大感触是,做sharepoint一定要做过非常大型的部署开发,没有经过这种淬炼,天天闷声研究,做一些页面功能,对技术提升毫无帮助 ...

  2. 自制基于HMM的中文分词器

    不像英文那样单词之间有空格作为天然的分界线, 中文词语之间没有明显界限.必须采用一些方法将中文语句划分为单词序列才能进一步处理, 这一划分步骤即是所谓的中文分词. 主流中文分词方法包括基于规则的分词, ...

  3. [CSS3] 学习笔记-背景与边框相关样式

    1.与背景相关的新增属性 包括:backgroud-clip,backgroud-origin,backgroud-size <!DOCTYPE html> <html> &l ...

  4. JQuery之 serialize() 及serializeArray() 实例介绍

    这两个方法都是jq封装的,主要用于form表单. serialize(); 1.创建一个标准url编码显示的文本字符转: 2.操作的对象是表单元素结合的jq对象: serializeArray(); ...

  5. 比特(bit)、字,字节(B)存储单位之间的关系+其与操作系统位数的关系+不同编译器编译方式下数据类型的表示范围

    1.在表示网络传输速度中与表示存储单位的不同: 表示存储单位时:1kB=1024B,但在网络中表示传输速度是1KB=1000B 2.下面介绍表示存储单位时的关系及其与操作系统位数的关系: 1B=8bi ...

  6. 蓝桥网试题 java 基础练习 数列特征

    ----------------------------------- Collections.sort(list);是个好东西 但是要学会排列 然后你才能浪 -------------------- ...

  7. Python系列之Collections内置模块(2)

    defaultdict 返回一个类 dict 的对象,defaultdict 是内置的 dict 类的子类. 如果访问 dict 未初始化的 key 值时,会抛出 KeyError 异常. s_tup ...

  8. 一个web应用的诞生--数据存储

    上一章实现了登录的部分功能,之所以说是部分功能,是因为用户名和密码写成固定值肯定是不可以的,一个整体的功能,至少需要注册,登录,密码修改等,这就需要提供一个把这些值存储到数据库的能力. 当前的主流数据 ...

  9. JavaScript中国象棋程序(2) - 校验棋子走法

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第2节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  10. css3瀑布流

    css3虽然可以实现,不过要是真的运用到项目中还是老老实实写js吧 .container{ /*列的宽度*/ column-width:160px; -webkit-column-width:160p ...