无需后端服务器,异步读取和解释上传的文件。
网站是如何在不存储任何数据的情况下解释上传的文件的吗?FileReader API就是答案!它允许客户端应用程序异步读取和解释上传的文件。
要在您自己的客户端应用程序中执行此操作,您还需要了解File API
和Blob API
。这些是您将使用FileReader API
读取的对象。您还可以使用FileReader API
来分析从拖放操作中获取的文件。
注意:这与较新的
File System API
不同,后者提供了浏览器(和客户端JavaScript
)访问本地文件系统的功能。
尽管这个API
已经存在一段时间了(Chrome
在版本6中开始支持它),但现代用法的部分支持时间并不长,例如File API
(在Chrome 13
中发布)和File()
构造函数(在Chrome 38
中发布)。
基础知识
FileReader API
在基本用法中,可以与<input type="file" />
结合使用。一旦通过文件浏览器选择了文件,或者将文件拖放到文件字段上,就会在输入元素上创建一个新的File对象。
FileReader
可以与任何File
对象一起使用,但我们将探讨一个基本的用法场景。
让我们尝试将File对象传递给FileReader API
,如下所示:
1 | function readFile(file) { |
然而,上面的示例还不够完整。FileReader API
默认是异步的,并且不使用Promises
。相反,您可以监听几个事件。
现在,让我们专注于以下事件:
- load:在成功加载文件时触发
- error:在读取文件失败时触发请注意,在上面的示例中,我们将
1
2
3
4
5
6
7
8
9
10
11
12
13function readFile() {
const fileReader = new FileReader();
const resultContainer = document.getElementById('result');
const file = document.getElementById('uploaded-file').files[0];
if (file) {
fileReader.readAsText(file);
}
fileReader.addEventListener('load', () => {
resultContainer.innerText = fileReader.result
}, { once: true });
}resultContainer
的文本设置为FileReader
触发load事件后所获得的结果。
fileReader
对象上的result
属性正是您所期望的:FileReader
从文件中读取的内容包含在result
属性中。
虽然它无法读取每种类型文件的内容,但FileReader
提供了以下方法:
- readAsText()
- readAsDataURL()
- readAsArrayBuffer()
方法:readAsText()
首先是FileReader API
提供的非常基础的文本方法。您应该只在较小的文件上使用此方法,因为它会将整个文件读入内存。对于较大的文件,您应该使用readAsArrayBuffer()
,因为它返回一个Promise
,并且对于较大的文件更加可预测。
在上面的示例中,我们将传递给readFile()
的文件并记录readAsText
方法的结果。如果我们想读取任何类型的基于文本的文件,例如 .txt
、.csv
等,这将非常有用。
1 | <label> |
1 | function readFile() { |
方法:readAsDataURL()
此方法可用于读取图像,类似于如果它们是数据URL
字符串时与图像进行交互的方式。这正是此方法的作用:将图像作为base64
编码的数据URL
返回。
注意:它是
readAsDataURL
-URL
中所有字母都大写 - 而不是readAsDataUrl
。使用后者会导致错误 - 它是区分大小写的。
让我们看下面的示例:
1 | <!-- 不要忘记以语义化方式编写HTML! --> |
请注意,我使用accept
属性将上传的文件限制为图像类型的MIME
类型。查阅MDN
上有关如何指定要接受的文件类型的信息。
1 | function readImage() { |
在上面的示例中,我们:
- 创建一个
FileReader
- 然后监听
load
事件的发生(意味着文件读取会话成功) - 然后创建一个
<img>
元素,并将图像作为数据URL
放入src
属性中 - 最后,将创建的img添加到我们为图像创建的
<div>
容器中1
2
3
4
5
6
7
8
9<label>
Upload file
<input type="file" id="testfile" accept="image/*" onchange="readImage()">
</label>
<br> <br>
<div>
Image that was uploaded:
<div id="result"></div>
</div>此API非常适用于简单的浏览器操作,甚至可以用于上传图像/文本/文件到后端服务器时的实时状态更新。要在主要社交网络上更新个人资料图片?您可以使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function readImage() {
const fileReader = new FileReader();
const file = document.querySelector("input[type=file]").files[0];
if (file) {
fileReader.readAsDataURL(file);
}
fileReader.addEventListener(
"load",
() => {
const result = fileReader.result;
const resultContainer = document.getElementById("result");
const img = document.createElement("img");
img.src = result;
resultContainer.append(img);
},
{ once: true }
);
}FileReader API
来复制此操作。
FileReader事件
FileReader
上还有几个其他事件值得了解。
- abort - 文件读取已被中止(取消)
- progress - 在读取期间定期触发
- loadstart / loadend - 可用于在文件加载开始或结束时触发某些操作
这些事件是从ProgressEvent
接口扩展的。通过监听FileReader
上的progress
事件,您可以通过将ProgressEvent
上的loaded
除以total
属性来计算文件读取进度。
1 | fileReader.addEventListener("progress", (event) => { |
进阶
FileReader
是一个很棒的API
,可用于许多客户端应用程序。它是许多您可能已经使用的应用程序的基础。