用javascript实现base64编码器

来源:互联网 发布:ac尼尔森中国奶粉数据 编辑:程序博客网 时间:2024/06/05 09:07

原理

  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   41    B    9     J    17    R    25    Z    33    h    41    p    49    x    57    52    C    10    K    18    S    26    a    34    i    42    q    50    y    58    63    D    11    L    19    T    27    b    35    j    43    r    51    z    59    74    E    12    M    20    U    28    c    36    k    44    s    52    0    60    85    F    13    N    21    V    29    d    37    l    45    t    53    1    61    96    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编码的字符串数据。

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);//JUU1JUIwJThGJUU3JTgxJUFCJUU2JTlGJUI0console.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>  
复制代码

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小鸡站不起来了怎么办 感冒了流清鼻涕怎么办 哈士奇又吐又拉怎么办 怀孕乳房长妊娠纹怎么办 乳房长妊娠纹了怎么办 宝宝忌奶晚上哭怎么办 20岁胸下垂松软怎么办 断奶时乳房有肿块怎么办 孩子断奶后乳房变小怎么办 断奶了月经不来怎么办 钥匙在门上拔不出来怎么办 钥匙拔不下来了怎么办 养了几天鱼死了怎么办 乌龟的眼睛肿了怎么办 手被鱼刺扎了怎么办 被鱼刺扎手肿了怎么办 手被桂鱼扎了怎么办 三岁宝宝卡鱼刺怎么办 一岁宝宝卡鱼刺怎么办 鱼刺卡在胸口了怎么办 婴儿被鱼刺卡了怎么办 幼儿被鱼刺卡到怎么办 鱼刺被吞下去了怎么办 喉咙卡到鱼刺下不去怎么办 被小鱼刺卡了怎么办 晚上被鱼刺卡到怎么办 一个小鱼刺卡了怎么办 卡了一个小鱼刺怎么办 鱼刺卡在气管里怎么办 刺蛾幼虫 蛰了怎么办 被杨树辣子蛰了怎么办 蜇了老子蜇了怎么办 被刺蛾幼虫蛰了怎么办 孕妇被蚊虫叮咬发痒怎么办 白掌叶子尖发黄怎么办 白掌叶子卷了怎么办 白掌叶子全软了怎么办? 发财树有黄斑了怎么办 幸福树叶子蔫了怎么办 幸福树枝条塌了怎么办? 幸福树叶子嫣了怎么办