一、blob(类文件对象)
Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
(1)Blob 创建
1.1创建
new Blob(array, options);
array:由 ArrayBuffer、ArrayBufferView、Blob、DOMString 等对象构成的,将会被放进 Blob;
options:可选的 BlobPropertyBag 字典,它可能会指定如下两个属性
type:默认值为 "",表示将会被放入到blob中的数组内容的 MIME 类型。endings:默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入,不常用。
1.2示例
const blob = new Blob(["Hello World"], {type: "text/plain"});
console.log(blob.size); // 11
console.log(blob.type); // "text/plain"
(2)Blob 分片
1.1创建
const blob = instanceOfBlob.slice([start [, end [, contentType]]]};
其有三个参数:
start:设置切片的起点,即切片开始位置。默认值为 0,这意味着切片应该从第一个字节开始;end:设置切片的结束点,会对该位置之前的数据进行切片。默认值为blob.size;contentType:设置新 blob 的 MIME 类型。如果省略 type,则默认为 blob 的原始值。
1.2示例
const iframe = document.getElementsByTagName("iframe")[0];
const blob = new Blob(["Hello World"], {type: "text/plain"});
const subBlob = blob.slice(0, 5); // Hello
iframe.src = URL.createObjectURL(subBlob);
二、File(blob类型的特殊对象、储存文件)
File 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。Blob 的属性和方法都可以用于 File 对象(File 对象中只存在于浏览器环境中,在 Node.js 环境中不存在。)
1.1特殊属性
lastModified:引用文件最后修改日期,为自1970年1月1日0:00以来的毫秒数;lastModifiedDate:引用文件的最后修改日期;name:引用文件的文件名;size:引用文件的文件大小;type:文件的媒体类型(MIME);webkitRelativePath:文件的路径或 URL。
1.2获取方式
-
<input>元素上选择文件后返回的 FileList 对象;<input type="file" id="fileInput" multiple="multiple"> const fileInput = document.getElementById("fileInput"); fileInput.onchange = (e) => { console.log(e.target.files); } -
文件拖放
<div id="drop-zone"></div> const dropZone = document.getElementById("drop-zone"); dropZone.ondragover = (e) => { e.preventDefault(); } dropZone.ondrop = (e) => { e.preventDefault(); const files = e.dataTransfer.files; console.log(files) }
三、fileReader(读取文件并提取其内容)
FileReader 是一个异步 API,用于读取文件并提取其内容以供进一步使用。
1.1创建
const reader = new FileReader();
1) 属性
error:表示在读取文件时发生的错误;result:文件内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。readyState:表示FileReader状态的数字。 0 : 还没有加载任何数据, 1:数据正在被加载 , 2 : 已完成全部的读取请求。
2)方法
readAsArrayBuffer():读取指定 Blob 中的内容,完成之后,result属性中保存的将是被读取文件的ArrayBuffer数据对象;FileReader.readAsBinaryString():读取指定 Blob 中的内容,完成之后,result属性中将包含所读取文件的原始二进制数据;FileReader.readAsDataURL():读取指定 Blob 中的内容,完成之后,result属性中将包含一个data: URL格式的 Base64 字符串以表示所读取文件的内容。FileReader.readAsText():读取指定 Blob 中的内容,完成之后,result属性中将包含一个字符串以表示所读取的文件内容。
3)事件
abort:该事件在读取操作被中断时触发;error:该事件在读取操作发生错误时触发;load:该事件在读取操作完成时触发;progress:该事件在读取 Blob 时触发。
1.2示例
<input type="file" id="fileInput">
const fileInput = document.getElementById("fileInput");
const reader = new FileReader();
fileInput.onchange = (e) => {
reader.readAsText(e.target.files[0]);
}
reader.onload = (e) => {
console.log(e.target.result);
}
<input type="file" id="fileInput" />
<img id="preview" />
const fileInput = document.getElementById("fileInput");
const preview = document.getElementById("preview");
const reader = new FileReader();
fileInput.onchange = (e) => {
reader.readAsDataURL(e.target.files[0]);
};
reader.onload = (e) => {
preview.src = e.target.result;
console.log(e.target.result);
};
const reader = new FileReader();
reader.onprogress = (e) => {
if (e.loaded && e.total) {
const percent = (e.loaded / e.total) * 100;
console.log(`上传进度: ${Math.round(percent)} %`);
}
});
四、ArrayBuffer(通用的、固定长度的原始二进制数据缓冲区)
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 的内容不能直接操作,只能通过 DataView 对象或 ArrayBuffer 对象用来访问
- TypedArray:用来生成内存的视图,通过9个构造函数,可以生成9种数据格式的视图。
- DataViews:用来生成内存的视图,可以自定义格式和字节序。
(1)ArrayBuffer
1、new ArrayBuffer()
new ArrayBuffer(bytelength)
- 参数:它接受一个参数,即 bytelength,表示要创建数组缓冲区的大小(以字节为单位。);
- 返回值:返回一个新的指定大小的ArrayBuffer对象,内容初始化为0。
2、ArrayBuffer.prototype.byteLength
const buffer = new ArrayBuffer(16);
console.log(buffer.byteLength); // 16
只读属性,表示 ArrayBuffer 的 byte 的大小,在 ArrayBuffer 构造完成时生成,不可改变
3、ArrayBuffer.prototype.slice()
const buffer = new ArrayBuffer(16);
console.log(buffer.slice(0, 8)); // 8
方法可以用来截取 ArrayBuffer 实例,它返回一个新的 ArrayBuffer
4、ArrayBuffer.isView(),
判断参数是否是 TypedArray 实例或者 DataView 实例, typedArray或者DataView的实例为true
const buffer = new ArrayBuffer(16);
ArrayBuffer.isView(buffer) // false
const view = new DataView(buffer);
ArrayBuffer.isView(view) // true
(2)typedArray
TypedArray 对象一共提供 9 种类型的视图,每一种视图都是一种构造函数
| 元素 | 类型化数组 | 字节 | 描述 |
|---|---|---|---|
| Int8 | Int8Array | 1 | 8 位有符号整数 |
| Uint8 | Uint8Array | 1 | 8 位无符号整数 |
| Uint8C | Uint8ClampedArray | 1 | 8 位无符号整数 |
| Int16 | Int16Array | 2 | 16 位有符号整数 |
| Uint16 | Uint16Array | 2 | 16 位无符号整数 |
| Int32 | Int32Array | 4 | 32 位有符号整数 |
| Uint32 | Uint32Array | 4 | 32 位无符号整数 |
| Float32 | Float32Array | 4 | 32 位浮点 |
| Float64 | Float64Array | 8 | 64 位浮点 |
Uint8Array: 将 ArrayBuffer 中的每个字节视为一个整数,可能的值从 0 到 255 (一个字节等于 8 位)。 这样的值称为“8 位无符号整数”。
Uint16Array:将 ArrayBuffer 中任意两个字节视为一个整数,可能的值从 0 到 65535。 这样的值称为“16 位无符号整数”。
Uint32Array: 将 ArrayBuffer 中任何四个字节视为一个整数,可能值从 0 到 4294967295,这样的值称为“32 位无符号整数”
那typedArray格式的数组和数组有什么区别呢?
- 类型化数组的元素都是连续的,不会为空;
- 类型化数组的所有成员的类型和格式相同;
- 类型化数组元素默认值为 0;
- 类型化数组本质上只是一个视图层,不会存储数据,数据都存储在更底层的 ArrayBuffer 对象中。
1、new TypedArray()
new Int8Array(length);
new Int8Array(typedArray);
new Int8Array(object);
new Int8Array(buffer [, byteOffset [, length]]);
new Int8Array(new Uint8Array(length));
new Int8Array(16);
new Int8Array([1,2,3,4]);
new Int32Array(new ArrayBuffer(8), 4)
new Int8Array(new Int8Array(6));
2、BYTES_PER_ELEMENT
表示这种数据类型占据的字节数:
Int8Array.BYTES_PER_ELEMENT // 1
Uint8Array.BYTES_PER_ELEMENT // 1
Int16Array.BYTES_PER_ELEMENT // 2
Uint16Array.BYTES_PER_ELEMENT // 2
Int32Array.BYTES_PER_ELEMENT // 4
Uint32Array.BYTES_PER_ELEMENT // 4
Float32Array.BYTES_PER_ELEMENT // 4
Float64Array.BYTES_PER_ELEMENT // 8
或者
const buffer = new ArrayBuffer(16);
const view = new Uint32Array(buffer);
console.log(view.BYTES_PER_ELEMENT); // 4
3、 TypedArray.prototype.buffer
返回内存中对应的 ArrayBuffer对象,只读属性
const a = new Uint32Array(8);
const b = new Int32Array(a.buffer);
console.log(a, b);
4、TypedArray.prototype.slice
可以返回一个指定位置的新的 TypedArray实例。
const view = new Int16Array(8);
console.log(view.slice(0 ,5));
5、byteLength 和 length
byteLength:返回 TypedArray 占据的内存长度,单位为字节;length:返回 TypedArray 元素个数;
const view = new Int16Array(8);
view.length; // 8
view.byteLength; // 16
(3)DataView
DataView 视图是一个可以从 二进制 ArrayBuffer 对象中读写多种数值类型的底层接口
new DataView(buffer [, byteOffset [, byteLength]])
buffer:一个已经存在的 ArrayBuffer 对象,DataView 对象的数据源。byteOffset:可选,此 DataView 对象的第一个字节在 buffer 中的字节偏移。如果未指定,则默认从第一个字节开始。byteLength:可选,此 DataView 对象的字节长度。如果未指定,这个视图的长度将匹配 buffer 的长度
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
console.log(view);
1、buffer、byteLength、byteOffset
buffer:返回对应的ArrayBuffer对象;byteLength:返回占据的内存字节长度;byteOffset:返回当前视图从对应的ArrayBuffer对象的哪个字节开始。
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
view.buffer;
view.byteLength;
view.byteOffset;
2、读取数据
DataView 实例提供了以下方法来读取内存,它们的参数都是一个字节序号,表示开始读取的字节位置:
- getInt8:读取1个字节,返回一个8位整数。
- getUint8:读取1个字节,返回一个无符号的8位整数。
- getInt16:读取2个字节,返回一个16位整数。
- getUint16:读取2个字节,返回一个无符号的16位整数。
- getInt32:读取4个字节,返回一个32位整数。
- getUint32:读取4个字节,返回一个无符号的32位整数。
- getFloat32:读取4个字节,返回一个32位浮点数。
- getFloat64:读取8个字节,返回一个64位浮点数。
const buffer = new ArrayBuffer(24);
const view = new DataView(buffer);
// 从第1个字节读取一个8位无符号整数
const view1 = view.getUint8(0);
// 从第2个字节读取一个16位无符号整数
const view2 = view.getUint16(1);
// 从第4个字节读取一个16位无符号整数
const view3 = view.getUint16(3);
5、写入内存
setInt8:写入1个字节的8位整数。
setUint8:写入1个字节的8位无符号整数。
setInt16:写入2个字节的16位整数。
setUint16:写入2个字节的16位无符号整数。
setInt32:写入4个字节的32位整数。
setUint32:写入4个字节的32位无符号整数。
setFloat32:写入4个字节的32位浮点数。
setFloat64:写入8个字节的64位浮点数。
五、Object URL
Object URL(MDN定义名称)又称Blob URL(W3C定义名称),是HTML5中的新标准
其实Blob URL/Object URL 是一种伪协议,允许将 Blob 和 File 对象用作图像、二进制数据下载链接等的 URL 源
<input type="file" id="fileInput" />
<img id="preview" />
const fileInput = document.getElementById("fileInput");
const preview = document.getElementById("preview");
fileInput.onchange = (e) => {
preview.src = URL.createObjectURL(e.target.files[0]);
console.log(preview.src);
};
- createObjectURL
- revokeObjectURL
六、Base64
Base64 是一种基于64个可打印字符来表示二进制数据的表示方法
atob():解码,解码一个 Base64 字符串;btoa():编码,从一个字符串或者二进制数据编码一个 Base64 字符串。
atob():解码,解码一个 Base64 字符串;
btoa():编码,从一个字符串或者二进制数据编码一个 Base64 字符串。
btoa("JavaScript") // 'SmF2YVNjcmlwdA=='
atob('SmF2YVNjcmlwdA==') // 'JavaScript'
七、格式转化
-
ArrayBuffer → blob
const blob = new Blob([new Uint8Array(buffer, byteOffset, length)]);
-
ArrayBuffer → base64
const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
-
base64 → blob
const base64toBlob = (base64Data, contentType, sliceSize) => {
const byteCharacters = atob(base64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
-
blob → ArrayBuffer
function blobToArrayBuffer(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject;
reader.readAsArrayBuffer(blob);
});
}
-
blob → base64
function blobToBase64(blob) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}
-
blob → Object URL
const objectUrl = URL.createObjectURL(blob);