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. Algo: Dynamic programming

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  2. leetcode-03-二叉树的锯齿层次遍历

    题目描述: 方法一: # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.va ...

  3. 高速网络下的http协议优化

    http协议是基于TCP协议,具备TCP协议的所有功能.但是与一般TCP的长连接不同的是http协议往往连接时间比较短,一个请求一个响应了事.但是总所周知,TCP协议除了具备可靠的传输以外,还有拥塞控 ...

  4. Audio 标签的使用和自己封装一个强大的React音乐播放器

    原文地址:https://www.dodoblog.cn/blog?id=5be84d5c70b2b617f27a4610 这篇文章主要介绍一下博客里的这个音乐播放器是怎么写的 为了更好的表达高深的东 ...

  5. PAT甲级——A1002 A+B for Polynomials

    This time, you are supposed to find A+B where A and B are two polynomials. Input Specification: Each ...

  6. Mysql千万级数据性能调优配置

    背景: 笔者的源数据一张表大概7000多万条,数据大小36G,索引6G,加起来表空间有40G+,类似的表有4张,总计2亿多条 数据库mysql,引擎为innodb,版本5.7,服务器内存256G,物理 ...

  7. C开发系列-include

    include 在include目录下有两个文件,分别为main.m, abc.txt main.m内容 #include <stdio.h> int main(){ #include & ...

  8. pymysql 使用

    适用环境 python版本 >=2.6或3.3 mysql版本>=4.1 安装 可以使用pip安装也可以手动下载安装. 使用pip安装,在命令行执行如下命令: 1 pip install  ...

  9. Codeforces 500D. New Year Santa Network

    题目大意 给你一颗有\(n\)个点的树\(T\),边上有边权. 规定,\(d(i,j)\)表示点i到点j路径上的边权之和. 给你\(q\)次询问,每次询问格式为\(i, j\),表示将按输入顺序排序的 ...

  10. Angularjs 1 使用filter格式化输出href

    Angularjs版本: 1.3.5 工作中,由于是多级菜单,如果上级菜单为空,就会访问Angularjs 默认的state,然后再展开菜单,我找资料之后,才知道是通过filter来格式化输出数据的, ...