一、字节
1.1 概念
字节(Byte)
是计算机信息技术用于计量存储容量的一种计量单位,也表示一些计算机编程语言中的数据类型和语言字符。
一个字节存储8位无符号数,储存的数值范围为0-255。
1.2 Byte与bit
数据存储
是以“字节”(Byte)
为单位,数据传输
大多是以“位”(bit,又名“比特”)为单位
,一个位就代表一个0或1(即二进制),每8个位(bit,简写为b)组成一个字节(Byte,简写为B),是最小一级的信息单位。
有控制码或非美标码的文件,通常不能在不同电脑系统间直接交换。这类文件有一个通称,叫“二进制文件”(Binary Files
)。
1 | 1字节(Byte)=8位(bit) |
二、编码
2.1 概念
在计算机中,所有的数据在存储和运算时都要使用二进制数表示(因为计算机用高电平和低电平分别表示1和0),例如,像a、b、c、d等52个字母(包括大写)以及0、1等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示。
而具体用哪些二进制数字表示哪个符号,当然每个人都可以约定自己的一套(这就叫编码
),而如果要想互相通信而不造成混乱,那么就必须使用相同的编码规则。美国有关的标准化组织就出台了ASCII编码
,统一规定了上述常用符号用哪些二进制数来表示。
2.2 编码标准
文字编码标准主要有ASCII
、GB2312
、GBK
、Unicode
等。
ASCII
:编码是美国信息交换标准编码(美标)。
GB2312
、GBK
、GB18030
:汉字字符编码方案的国家标准。
BIG5码
:针对繁体汉字的汉字编码,在台湾、香港的电脑系统中普遍应用。
Unicode
:宽字节字符集,它对每个字符都固定使用两个字节即16位表示(普及到东亚国家发展出的编码标准)(UCS4、UTF-8、UTF-16都是Unicode的编码方案。其中UTF-8因可以兼容ASCII
而被广泛使用。)。
Base64编码
:现有的字符集非常多,常用的有 UTF-8 / GBK
等, 这里面的某些字节在某些传输渠道。比如邮件传输就不支持上面ASCII
码中的控制字符, Base64
的创建就是为了解决此问题。
Base64
内的64是指64个字符, 分别是 A-Z, a-z, 0-9, +, /
,Base64 相应的索引表如下:
在 HTML
中可以嵌入 base64
编码的图片,可以减少网络请求。
浏览器都支持 Data URLs
,允许使用base64
对图片或其他文件的二进制数据进行编码,就可以将其作为文本字符串嵌入网页中。
Data URLs 由四个部分组成:前缀(data:
)、指示数据类型的 MIME
类型、如果非文本则为可选的 base64
标记、数据本身:
1 | data:[<mediatype>][;base64],<data> |
但需要注意的是:如果图片较大则不适合使用这种方式,因为图片经过 base64 编码后的字符串变大约三分之一,影响HTML 页面加载速度。
2.3 ASCII码与Base64的编解码
Base64
有64个字符, 2^6 = 64,所以每个Base64编码
字符可以用一个6位的二进制
来表示。这样的话如果有3个字节的二进制
, 可以用4位Base64字符
表示。
编码流程如下:
ASCII码
字符串根据ASCII码对照表转换为二进制数值
;- 把
二进制数值
按每6位
进行划分; - 然后
6位二进制
转化为十进制
根据对照表找到Base64编码字符
;
由图可知,Man
(3 字节)编码的结果为 TWFu
(4 字节),经过 base64 编码后体积会增加 1/3。Man
这个字符串的长度刚好是 3,可以用 4 个 base64 单元来表示。
如果待编码字符串的长度不是3的倍数,为了可以整除6编译出完整的字节数, 就需要使用 0 字节值在末尾补足,使其能够被 3 整除,然后再进行 base64 的编码。
如果有连续
6位都是0的话, 就用“=”来表示
。
base64编码与解码
- btoa():该函数能够基于二进制数据 “字符串” 创建一个 base64 编码的 ASCII 字符串。
- atob(): 该函数能够
解码
通过 base64 编码的字符串数据。
三、下载相关函数
3.1 Blob
3.1.1 概念
Blob(Binary Large Object)
表示二进制类型的大对象。在数据库管理系统中,将二进制数据存储为一个单一个体的集合。Blob 通常是影像、声音或多媒体文件。「在 JavaScript 中 Blob 类型的对象表示不可变的类似文件对象的原始数据。」
Blob 对象含有两个属性:size 和 type。其中 size
属性用于表示数据的大小(以字节为单位),type
是 MIME 类型
的字符串。
3.1.2 构造函数
1 | var aBlob = new Blob(blobParts, options); |
blobParts
:是一个由ArrayBuffer
,ArrayBufferView
,Blob
,DOMString
等对象构成的数组。DOMStrings
会被编码为UTF-8
。options
:一个可选的对象,包含以下两个属性:type
—— 默认值为""
,代表了将会被放入到 blob 中的数组内容的 MIME 类型。endings
—— 默认值为"transparent"
,用于指定包含行结束符\n
的字符串如何被写入。 它是以下两个值中的一个:"native"
,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者"transparent"
,代表会保持 blob 中保存的结束符不变。
1 | let myBlobParts = ['<html><h2>Hello Semlinker</h2></html>']; // an array consisting of a single DOMString |
3.2 Object URL
Object URL
是一种伪协议,也被称为 Blob URL
。允许 Blob
或 File
对象用作图像,下载二进制数据链接等的 URL 源。在浏览器中,使用 URL.createObjectURL
方法来创建 Blob URL
,该方法接收一个 Blob
对象,并为其创建一个唯一的 URL,形式为 blob:<origin>/<uuid>
,对应的示例如下:
1 | blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f641 |
虽然存储了URL → Blob
的映射,但 Blob 本身仍驻留在内存中,浏览器无法释放它。映射在文档卸载时自动清除,因此 Blob 对象随后被释放。但是,如果应用程序寿命很长,那不会很快发生。因此,如果创建了一个Blob URL
,即使不再需要该Blob
,它也会存在内存中。
针对这个问题,可以调用 URL.revokeObjectURL(url)
方法,从内部映射中删除引用,从而允许删除 Blob(如果没有其他引用),并释放内存。
3.3 ArrayBuffer
ArrayBuffer 对象用来表示「通用的、固定长度的」原始二进制数据缓冲区。** 「ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView
对象来操作」,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
3.4 Unit8Array
Uint8Array 数组类型表示一个 8 位无符号整型数组,创建时内容被初始化为 0。创建完后,可以以「对象的方式或使用数组下标索引的方式」 引用数组中的元素。
1 | new Uint8Array(); // ES2017 最新语法 |
3.5 Blob 与 ArrayBuffer
- 除非需要使用 ArrayBuffer 提供的写入/编辑的能力,否则 Blob 格式可能是最好的。
- Blob 对象是不可变的,而 ArrayBuffer 是可以通过 TypedArrays 或 DataView 来操作。
- ArrayBuffer 是存在内存中的,可以直接操作。而 Blob 可以位于磁盘、高速缓存内存和其他不可用的位置。
- 虽然 Blob 可以直接作为参数传递给其他函数,比如
window.URL.createObjectURL()
。但是,可能仍需要 FileReader 之类的 File API 才能与 Blob 一起使用。 - Blob 与 ArrayBuffer 对象之间是可以相互转化的:
- 使用 FileReader 的
readAsArrayBuffer()
方法,可以把 Blob 对象转换为 ArrayBuffer 对象; - 使用 Blob 构造函数,如
new Blob([new Uint8Array(data]);
,可以把 ArrayBuffer 对象转换为 Blob 对象。
- 使用 FileReader 的
四、文件下载
4.1 a标签下载
4.1.1 文件合成
merge-images 这个库提供 mergeImages(images, [options])
方法,可以实现图片合成的功能。调用该方法后会返回一个 Promise 对象,当异步操作完成后,合成的图片会以 Data URLs 的格式返回。
1 | const mergePicEle = document.querySelector("#mergedPic"); |
4.1.2 文件下载
1 | function dataUrlToBlob(base64, mimeType) { |
4.2 showSaveFilePicker API 下载
showSaveFilePicker 方法支持一个对象类型的可选参数,可包含以下属性:
excludeAcceptAllOption
:布尔类型,默认值为false
。默认情况下,选择器应包含一个不应用任何文件类型过滤器的选项(由下面的types
选项启用)。将此选项设置为true
意味着types
选项不可用。types
:数组类型,表示允许保存的文件类型列表。数组中的每一项是包含以下属性的配置对象:description(可选)
:用于描述允许保存文件类型类别。accept
:是一个对象,该对象的key
是 MIME 类型,值是文件扩展名列表。
1 | async function saveFile(blob, filename) { |
与a 标签下载 相比,showSaveFilePicker API 允许选择文件的下载目录、选择文件的保存格式和更改存储的文件名称。
4.3 FileSaver 下载
FileSaver.js 是在客户端保存文件的解决方案,非常适合在客户端上生成文件的 Web 应用程序。它是 HTML5 版本的 saveAs() FileSaver 实现,支持大多数主流的浏览器,其兼容性如下图所示:
1 | FileSaver saveAs( |
1 | // 保存文本 |
4.4 base64 格式下载
Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法。由于 2⁶ = 64 ,所以每 6 个比特为一个单元,对应某个可打印字符。3 个字节有 24 个比特,对应于 4 个 base64 单元,即 3 个字节可由 4 个可打印字符来表示。相应的转换过程如下图所示:
Base64 常用在处理文本数据的场合,表示、传输、存储一些二进制数据,包括 MIME 的电子邮件及 XML 的一些复杂数据。 在 MIME 格式的电子邮件中,base64 可以用来将二进制的字节序列数据编码成 ASCII 字符序列构成的文本。使用时,在传输编码方式中指定 base64。使用的字符包括大小写拉丁字母各 26 个、数字 10 个、加号 + 和斜杠 /,共 64 个字符,等号 = 用来作为后缀用途。
1 | async function download() { |
因为返回的是 base64
格式的图片,所以在调用 FileSaver
提供的 saveAs
方法前,需要将 base64
字符串转换成 blob
对象,该转换是通过以下的 base64ToBlob
函数来完成。
1 | function base64ToBlob(base64, mimeType) { |