Blob,ArrayBuffer,TypedArray,File,DataView,Canvas,image,文件上传与并发控制

855 阅读3分钟

Blob

Blob是一个不可变、原始数据的类文件对象

developer.mozilla.org/zh-CN/docs/…

const blob = new Blob(array, options)

由Blob构造函数可以得到blob实例,其中array为ArrayBuffer, TypedArray, Blob, DOMString。

ArrayBuffer

表示通用的、固定长度的原始二进制数据缓冲区。它是一个字节数组,通常在其他语言中称为“byte array”。

不能直接操作 ArrayBuffer 的内容,而是要通过类型数组对象(TypedArray)或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

TypedArray

对象描述了一个底层的二进制数据缓冲区(binary data buffer)的一个类数组视图(view)。事实上,没有名为 TypedArray 的全局属性,也没有一个名为 TypedArray 的构造函数

PS: ES 2017中可以 new typedArray()

以下数组的实例都是TypedArray

Int8Array(); 
Uint8Array(); 
Uint8ClampedArray();
Int16Array(); 
Uint16Array();
Int32Array(); 
Uint32Array(); 
Float32Array(); 
Float64Array();

DataView

从 二进制ArrayBuffer 对象中读写多种数值类型的底层接口

关系梳理 

图中缺少dataURL(base64)转为blob 

TypedArray,Blob(File),DataView,image,Canvas之间可以相互转换。

File与文件上传的两种方式

上传的文件是属于File类型的,可以通过FileReader系列方法将之编程arraybuffer/dataURL/Text。

示例代码

formData文件流

ElementUI中就是使用formData来上传文件的

补充:DataURL ---> Blob

进阶:文件切片上传

file对象是继承blob的,因此可以获取到ArrayBuffer,ArrayBuffer类对象有与普通数组一样的方法,因此通过slice方法截取数组就可以将文件切片(chunk)了。

另外未来识别不同的chunk,需要根据文件内容生成对应的hash值,最后服务端收取所有的hash值后合并

示例代码:下方的代码是基于单个切片串行上传的,因此只需要有一个全局的flag记录断点对应的文件切片即可。对于多个文件并发上传需要进一步优化

Base64上传

除了formData之外,也可以上传base64编码的字符串。

其实本质上就是将file/img转换成DataURL,根据前面的转换图,有以下两种方法

1. 使用FileReader的readAsDataURL方法

2. canvas.toDataURL()方法

补充

TypedArray与普通数组是由差别的:TypedArray不是普通数组,虽然两者有很多相同的方法。TypedArray不继承自Array,Array.isArray(TypedArray)结果是false。

另外,TypedArray的长度是固定的,不会变化,因此可以更改数组长度的方法如shift/pop/splice/push/unshift都不可以使用,此外,concat也不可以使用。

同时,也多了两个可以使用的方法set,subarray

最后

在切片上传中提到了串行上传和并行上传,那么就延伸出了一个问题,如何将上百个切片认为控制并发??

利用递归,代码如下:

模拟网络请求,其请求结果:

[ 0, 1000 ]
[ 2000, 3000 ]
[ 4000 ]