Blob
Blob 本质上也就是一个对象,可以用于表示一串数据。
我们可以创建一个 Blob 对象
js
const blob = new Blob(["this is a data","test"],{//第一个参数为一个数组,数组里放置数据,可以是图片,可以是文件,这里传一些字符串做测试
//第二个参数为配置对象
type:"text/plain"
});
console.log(blob);
我们就就可以看到这个对象
这个对象的 type 和 size 属性,相信不用多说,无非就是大小和类型。
创建一个 blob 之后,如何获取 blob 中的数据呢?就要通过实例方法了,实例方法中有一个 arrayBuffer(),该方法会返回一个 Promise,数据为一个 ArrayBuffer 对象,我们可以通过类型化数组或者 dataView 去操作这个 ArrayBuffer 对象,这里不多介绍。
除了这个方法之外,还有三个方法,分别是 slice(),text(),stream()
首先介绍前面两个,首先是 slice(),我们知道 blob 本质上就是一个文件,所以既然是文件,是二进制的数据,我们当然可以给他截取一部分出来,slice 方法就可以把一个文件截取一部分出来,blob.slice(start,end,MIME),这个方法就会将 blob 对象的第 start 字节开始,截取到 end 字节结束,截取出来的新 blob 类型为第三个参数指定的类型。
接下来就是 text() 方法,这个方法返回一个 Promise 对象,Promise 对象中的数据就是 blob 中的内容,这个内容使用 UTF-8 进行编码。
js
const blob = new Blob(["this is a data", "test"], {
type: "text/plain"
});
const firstBlob = blob.slice(0, 6, 'text/plain');
firstBlob.text().then(data => {
console.log(data);//输出this i
})js
const blob = new Blob(["this is a data", "test"], {
type: "text/plain"
});
blob.text().then(data => {
console.log(data);//this is a datatest
})File
File 类实际上就是 Blob 类的子类,也就可以认为 File 本质上就是一个特殊的 Blob
我们要获得一个 File 对象有三种方法
- 使用
File()构造函数创建文件对象 file类型的input元素中获取- dragAPI 中事件对象的
dataTransfer中获取
首先介绍使用构造函数来创建,这种方式很少见,File 构造函数中需要至少两个参数,第一个参数为文件,可以是字符串,可以是 ArrayBuffer,可以是数组。第二个参数为文件名,第三个就是一些配置对象,配置对象里可以配置两个属性,分别是 type 和lastModified,第一个参数我相信不用说,就是 MIME 类型,第二个参数就是最后一次修改的事件,默认就是当前的毫秒级时间戳。由于这种方式比较少见,所以这里我懒得演示了。
我们更多是通过读取 file 类型的 input 元素以及 dragAPI 来获取文件对象,其实读者到这里应该明白,拖拽 API 最大的用处其实是数据传输,而数据传输最有用的莫过于上传和下载文件。
首先,file 类型的 input 元素可以用于上传文件,很显然,当我们选中文件之后,这个 input 元素中肯定有一个文件对象,现在的问题是如何通过 JS 获取这个文件对象。
html
<!DOCTYPE html>
<html lang="cmn-hans">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<input type="file" multiple name="" id="">
</body>
<script>
const file = document.querySelector("input[type='file']");
file.addEventListener("change", e => {
console.log(e.target.files);//可以输出文件数组
});
</script>
</html>可以看到,在 file 类型的 input 元素中,有一个 files 属性,这个属性是一个伪数组,用于保存选中的多个 Files 对象。

同样,在拖拽事件对象的 datatransfer 属性中其实也有一个 files 属性,可以获取到当前拖入文件的 File 对象。
html
<!DOCTYPE html>
<html lang="cmn-hans">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<input type="file" multiple name="" id="">
</body>
<script>
document.addEventListener("dragover", e => {
e.preventDefault();
});
document.addEventListener("drop", e => {
e.preventDefault();
console.log(e.dataTransfer.files);
})
</script>
</html>
此时就拿到了拖入文件的 File 对象
文件对象中有一个webkitRelativePath 属性,改属性可以获取到文件的路径,但是这并不是一个标准属性。
FileReader
现在我们已经有了 File 对象了,实际上就已经在 JS 中拿到文件了,现在的问题是如何把这个文件读出来,要想把文件读出来,我们就需要一个文件读取器,也就是 FileReader 对象
我们可以直接使用构造函数生成一个 FileReader 对象
js
const fr = new FileReader();//这里就创建了一个FileReader对象文件读取器可以帮助我们异步读取文件内容,这个异步是基于事件的,而非 Promise,这个注意。
这个对象上有很多方法和属性
- error:返回读取文件时的错误信息
- readyState:返回当前读取的状态,0 表示已经创建,但是还没开始读,1 表示正在读取,2 表示读取完毕
- result:返回文件的内容,这个属性只有当 readyState 为 2 的时候,也就是读取完毕的时候才生效,这个文件的格式取决于你用什么格式去读取的文件。
- readAsArrayBuffer ():以 ArrayBuffer 的格式读取文件
- readAsText ():以字符串的形式读取文件
- readAsDataUrl ():以 base 64 编码读取文件,一般读取图片用这个
- abort ():终止读取,调用之后 readyState 变为 2
当我们调用这些方法之后,就会自动开始读取文件,那读取文件一定是一个异步操作,我们如何判断文件读取完成了呢?很简单,就使用事件来完成这个异步处理,文件读取器中有一些事件可供我们使用
- abort:中止读取的时候触发
- error:读取出现错误的时候触发
- load:读取成功的时候触发
- loadend:文件读取完成就触发,哪怕读取出现了问题也触发
- loadstart:文件开始读取的时候触发
- progress:文件读取过程中频繁触发,可以用来做进度条
这些事件的事件对象中添加了以下属性可供我们使用:
- lengthComputable:布尔属性,表示此次读取的文件是否可计算
- loaded:一个 64 位无符号整数,表示已经读取的数据量
- total:一个 64 位无符号整数,表示数据总量
这里我们做一个简单的效果出来
html
<!DOCTYPE html>
<html lang="cmn-hans">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<img class="img" src="" alt="">
</body>
<script>
/**
* 初始化页面中的图像元素,并设置事件监听器以处理文件的拖放操作。
* 该代码段不接受参数,也不返回任何值。
*/
const img = document.querySelector(".img"); // 获取页面中类名为 img 的元素
// 监听文档上的拖动事件,阻止默认行为以允许拖放
document.addEventListener("dragover", e => {
e.preventDefault();
});
// 监听文档上的放下事件,阻止默认行为并处理拖放的文件
document.addEventListener("drop", e => {
e.preventDefault();
// 创建一个 FileReader 对象以读取拖放的文件
const fr = new FileReader();
// 当文件读取完成时,将图片数据赋值给 img 元素的 src 属性
fr.addEventListener("load", e => {
img.src = e.target.result;
});
// 读取拖放文件的数据,将其作为 Data URL 加载
fr.readAsDataURL(e.dataTransfer.files[0]);
})
</script>
</html>以上代码实现了,当我们拖拽一张图片进入网页的时候,让 img 元素显示该图片。
这里只演示了读取图片,我们当然可以选择以 ArrayBuffer 的形式读取文件,或者以字符串的形式读取为文本,总之我们只要在 load 事件中拿到 FileReader 的 result 属性即可。
这里读者可能会联想到
Blob中的 text 方法,这个方法可以返回一个 Promise,数据就是 Blob 对象中的字符串,以 UTF-8 编码。这个读取器的 readAsText 方法会更加强大,可以传入第二个参数,默认是 UTF-8,可以以其他的编码格式读取。