一图即可理解关系
Blob
定义
一个包含有只读原始数据的类文件对象。通俗讲就是不可修改的二进制文件
创建一个blob对象
let aBlob = new Blob( array, options );
Blob对象的属性
- size:数据的字节大小(只读)
- type:数据的MIME类型,例如'image/jpeg'(只读) (MIME:描述消息内容类型的因特网标准)
Blob对象的方法
Blob.slice(start, end ,contentType) contentType(可选):表示提取出来的数据的MIME类型。如果不指定,则新Blob对象的MIME类型将与原Blob对象相同。
const blob = new Blob(["<p>HELLO</p>"], {type: "text/html"});
const subBlob = blob.slice(0, 6, "text/html"); //Blob {size: 6, type: 'text/html'}
File
概念
File就是文件,继承自Blob,也是二进制对象,也有自己特有的属性和方法,通常用在<input type="file">
选择的FileList
对象,或者是使用拖拽操作产生的的DataTransfer
对象。
创建一个blob对象
var myFile = new File(array, name,options);
File对象属性
- name:文件名
- size:文件大小
- lastModified :最后修改时间(时间戳)
- lastModifiedDate:最后修改时间Data对象
- type:MIME类型
File对象方法
继承自Blob
的slice
方法
ArrayBuffer
概念
ArrayBuffer是内存上一段二进制数据,我们可以借助工具TypedArray、DataView对它进行读写
和Blob关系
ArrayBuffer是底层二进制数据,可以借助工具进行读写,而Blob是对底层二进制数据的封装,我们拿到的就是一个整体,能够读取他的大小,类型,但是不能看到细节
Blob可以接受一个ArrayBuffer作为参数生成一个Blob对象,此行为就相当于对ArrayBuffer数据做一个封装,之后就是以整体的形式展现了
Blob作为一个整体文件,适合用于传输;而只有需要关注细节(比如要修改某一段数据时),才需要用到ArrayBuffer
用法
创建,属性,方法
const buffer = new ArrayBuffer(16);
console.log(buffer.byteLength) // 16
console.log(buffer.slice(0, 8)) //ArrayBuffer(8)
ArrayBuffer.isView()
用来判断参数是否是 TypedArray 实例或者 DataView 实例:
const buffer = new ArrayBuffer(16);
ArrayBuffer.isView(buffer) // false
const view = new Uint32Array(buffer);
ArrayBuffer.isView(view) // true
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 位浮点 |
这些类型化数组的特点:元素都是连续的,不会为空;所有成员的类型和格式相同,默认值为 0;本质上只是一个视图层,不会存储数据,数据都存储在更底层的 ArrayBuffer 对象中。
创建
new Int8Array(length);
new Int8Array(typedArray);
new Int8Array(object);
new Int8Array(buffer [, byteOffset [, length]]);
let view = new Int8Array(16);
view[0] = 10;
view[10] = 6;
console.log(view); //Int8Array(16) [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, buffer: ArrayBuffer(16), byteLength: 16, byteOffset: 0, length: 16, Symbol(Symbol.toStringTag): 'Int8Array']
let view = new Int8Array(new Uint8Array(6));
view[0] = 10;
view[3] = 6;
console.log(view); //Int8Array(6) [10, 0, 0, 6, 0, 0, buffer: ArrayBuffer(6), byteLength: 6, byteOffset: 0, length: 6, Symbol(Symbol.toStringTag): 'Int8Array']
let view = new Int8Array([1, 2, 3, 4, 5]);
view[0] = 10;
view[3] = 6;
console.log(view); //Int8Array(5) [10, 2, 3, 6, 5, buffer: ArrayBuffer(5), byteLength: 5, byteOffset: 0, length: 5, Symbol(Symbol.toStringTag): 'Int8Array']
let view = new Int16Array(new ArrayBuffer(8))
console.log(view) //Int16Array(4) [0, 0, 0, 0, buffer: ArrayBuffer(8), byteLength: 8, byteOffset: 0, length: 4, Symbol(Symbol.toStringTag): 'Int16Array']
let view2 = new Int8Array(new ArrayBuffer(8),1)
console.log(view2) //Int8Array(7) [0, 0, 0, 0, 0, 0, 0, buffer: ArrayBuffer(8), byteLength: 7, byteOffset: 1, length: 7, Symbol(Symbol.toStringTag): 'Int8Array']
属性
-
buffer:返回内存中对应的 ArrayBuffer对象,只读属性
-
byteLength
:返回 TypedArray 占据的内存长度,单位为字节; -
length
:返回 TypedArray 元素个数;
const view = new Int32Array(8)
console.log(view.buffer); // ArrayBuffer(32)
console.log(view.byteLength); //32
console.log(view.length); //8
DataView
DataView 视图是一个可以从 二进制 ArrayBuffer 对象中读写多种数值类型的底层接口,使用它时,不用考虑不同平台的字节序问题。
创建
new DataView(buffer [, byteOffset [, byteLength]])
属性
buffer
:返回对应的ArrayBuffer对象;byteLength
:返回占据的内存字节长度;byteOffset
:返回当前视图从对应的ArrayBuffer对象的哪个字节开始。
const view = new DataView(new ArrayBuffer(16));
console.log(view); //DataView(16)
console.log(view.byteLength); //16
console.log(view.byteOffset); //0
写入和读取内存
写入(位置,整数数据)
- setInt8:写入1个字节的8位整数。
- setUint8:写入1个字节的8位无符号整数。
- setInt16:写入2个字节的16位整数。
- setUint16:写入2个字节的16位无符号整数。
- setInt32:写入4个字节的32位整数。
- setUint32:写入4个字节的32位无符号整数。
- setFloat32:写入4个字节的32位浮点数。
- setFloat64:写入8个字节的64位浮点数。
读取(位置)
- getInt8:读取1个字节,返回一个8位整数。
- getUint8:读取1个字节,返回一个无符号的8位整数。
- getInt16:读取2个字节,返回一个16位整数。
- getUint16:读取2个字节,返回一个无符号的16位整数。
- getInt32:读取4个字节,返回一个32位整数。
- getUint32:读取4个字节,返回一个无符号的32位整数。
- getFloat32:读取4个字节,返回一个32位浮点数。
- getFloat64:读取8个字节,返回一个64位浮点数。
let view = new DataView(new ArrayBuffer(16))
view.setInt16(0,100);
view.getInt8(0); //0
view.getInt8(1); //100
FileReader
FileReader 可以将 Blob 读取为不同的格式。
基本使用
创建
const reader = new FileReader();
属性
error
:表示在读取文件时发生的错误;result
:文件内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。readyState
:表示FileReader
状态的数字。0没有加载;1加载中;2已完成。
方法
readAsArrayBuffer(
Blob)
:读取指定 Blob 中的内容,完成之后,result
属性中保存的将是被读取文件的ArrayBuffer
数据对象;FileReader.readAsBinaryString(
Blob)
:读取指定 Blob 中的内容,完成之后,result
属性中将包含所读取文件的原始二进制数据;FileReader.readAsDataURL(
Blob)
:读取指定 Blob 中的内容,完成之后,result
属性中将包含一个data: URL
格式的 Base64 字符串以表示所读取文件的内容。FileReader.readAsText(
Blob)
:读取指定 Blob 中的内容,完成之后,result
属性中将包含一个字符串以表示所读取的文件内容。
事件处理
abort
:该事件在读取操作被中断时触发;error
:该事件在读取操作发生错误时触发;load
:该事件在读取操作完成时触发;progress
:该事件在读取 Blob 时触发。
可通过前置 on或者addEventListener形式来监听。
例子
将上传的图片显示在页面上
<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);
};
Object URL
Object URL又称Blob URL,是HTML5中的新标准。平时看到的blob:https://www.youtube.com/fd40f316-424 就是Object URL;我们可以在<img>
、<script>
标签中或者 <a>
和 <link>
标签的 href
属性中使用这个 URL。
方法
createObjectURL(File/Blob);
revokeObjectURL(objectURL);
例子
同样的将上传的图片显示在页面上,可以改写成
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);
};
Base64
Base64 是一种基于64个可打印字符来表示二进制数据的表示方法。
方法
atob()
:解码,解码一个 Base64 字符串;btoa()
:编码,从一个字符串或者二进制数据编码一个 Base64 字符串。
btoa("JavaScript") // 'SmF2YVNjcmlwdA=='
atob('SmF2YVNjcmlwdA==') // 'JavaScript'
应用场景
canvas 画布内容生成 base64 编码格式的图片
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext("2d");
const dataUrl = canvas.toDataURL();
readAsDataURL()
方法把上传的文件转为base64格式的data URI(之前例子已有体现)
img
标签和background
的 url
属性都支持使用base64 格式的图片,这样做也可以减少 HTTP 请求
FormData
使用FormData我们可以异步上传一个二进制文件,而这个二进制文件,就是我们上面讲的Blob/File对象。
常用方法
-
append(name, value, filename?): 向FormData对象中添加一个新的键值对。
name
是字段的名称,value
是字段的值,filename
是可选的,用于在添加文件时指定文件的名称。 -
delete(name): 从FormData对象中删除指定名称的键值对。如果成功删除,则返回
true
;如果指定的键不存在,则返回false
。 -
get(name): 获取FormData对象中指定名称的第一个值。如果找到了对应的值,则返回该值;否则,返回
null
。 -
getAll(name): 获取FormData对象中所有指定名称的值,返回一个数组。如果找到了对应的值,则返回一个包含这些值的数组;如果没有找到,则返回一个空数组。
-
has(name): 返回一个布尔值,表明FormData对象是否包含指定名称的键值对。如果包含,则返回
true
;否则,返回false
。 -
set(name, value, filename?): 设置FormData对象中指定名称的值。如果该名称已存在,则会覆盖原有的值。
filename
参数同样用于文件上传时指定文件名,是可选的。 -
entries(): 返回一个迭代器,包含FormData对象中的每个键值对。这个迭代器可以被用于
for...of
循环来遍历FormData对象中的所有键值对。 -
forEach(callback): 遍历FormData对象中的所有键值对,并对每个键值对执行指定的回调函数。回调函数接收三个参数:键名(key)、键值(value)和FormData对象本身(formData)。
-
keys(): 返回一个迭代器,包含FormData对象中的所有键名。这个迭代器可以被用于
for...of
循环来获取所有的键名。 -
values(): 返回一个迭代器,包含FormData对象中的所有值。这个迭代器可以被用于
for...of
循环来获取所有的值。
文件上传例子
var formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456); //数字 123456 会被立即转换成字符串 "123456"
// HTML 文件类型 input,由用户选择
formData.append("userfile", fileInputElement.files[0]);
var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php");
request.send(formData);