最近解决一个前端文件上传需求时,对于二进制内容的加解码有点困惑,同时对于前端相关 api 有些生疏。
FileReader
FileReader 类:仅做必要解释,具体查看 mdn
- 相关属性:result 文件的内容
- 事件
- onload 完成时触发
- onloadend 失败或完成均触发
- 方法
- readAsArrayBuffer 读取为 ArrayBuffer 对象
- readAsBinaryString 不推荐使用,草案中被废除,使用 ArrayBuffer 代替
- readAsDataURL 读取为 base64 编码
- readAsText 特殊编码转换为字符串,默认 utf-8
- readAsBinaryString 使用按照字节读取内容,并进行编码,由于读取后内容被编码为字符,大小会收到影响,因此不适合传输
- readAsArrayBuffer 按字节去读内容,并转换为 ArrayBuffer 对象,直接在网络传输二进制内容,本身 ArrayBuffer 中的内容对外是不可见的,若要查看其中的内容,就要引入另一个概念:类型化数组
- 使用 readAsText 读取非文本文件,可以用于传输吗?本质上传输应该是没有问题的,都可以还原成二进制,而且根据约定规则进行解码
编码基础
计算机在物理内存上存放的都是二进制文件,所以文本文件和二进制文件的主要区别是逻辑上的而不是物理上的。
从文件的编码方式来看,可以分为文本文件和二进制文件。
文本文件是基于字符编码的文件,常见的有 ASCII、Unicode 等,二进制文件是基于值编码的文件,可以看成是变长编码,你可以根据自己的需要,决定多少个比特代表一个值。
ASCII 文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的 ASCII 码。ASCII 码文件可在屏幕上按字符显示。
二进制文件是按二进制的编码方式来存放文件的。二进制文件虽然也可在屏幕上显示,但其内容无法读懂。C 系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把这种文件称作“流式文件”。
常用操作
TypedArray 与 ArrayBuffer 互转
- buffer = typedArray.buffer
- typedArray = new TypedArray(buffer)
ArrayBuffer 常见来源
- xhr/fetch 读取远程文件,指定 responseType 为 arraybuffer
- 本地选择文件,通过 FileReader 对象读取 File 或 Blob 对象
File 或 Blob 对象
- 本地选择文件得到
- xhr/fetch 读取远程文件,指定 responseType 为 blob
- 构造函数创建,new Blob([buffer])
DataURL 与 ObjectURL
- readAsDataURL
- canvas.toDataURL
- URL.createObjectURL(blob):对象生成一个地址来表示 Blob 数据,在不需要使用该对象以后要显式调用 URL.revokeObjectURL() 来释放它们
Base64 编码
- 使用大小写字母,数字,+ 和 64 个字符来编码数据,所以称为 Base64,经编码后,文本体积会变大 1/3
- 在浏览器中,可以使用 atob 和 btoa 编码解码数据