掌握 File API 这篇就够了
File API 是为了让 Web 开发者能以安全的方式访问客户端机器上的文件,从而更好地与这些文件交互而设计的。
File API 提供了丰富的功能,让Web开发者能够轻松处理文件。掌握File API 首先要理解和掌握三种类型 File、FileReader和FileReaderSync。
File类型使得对上传文件的信息获取变得简单,
而FileReader类型则允许异步读取文件内容,适用于处理大文件或实现文件预览。
FileReaderSync类型则提供了在Web Workers中进行同步文件读取的机制。
File 类型
HTML5 在 DOM 上为文件输入元素添加了 files 集合。
当用户在文件字段中选择一个或多个文件时, 这个 files 集合会包含一组 File 对象, 表示被选中的文件。每个 File 对象都有一些只读属性:
- name: 本地系统中的文件名
- size: 以字节(Byte)计的文件大小
- type: 包含文件 MIME 类型的字符串
- lastModifiedDate: 表示文件最后修改时间的字符串。(仅Chrome支持)
代码示例
下面的例子描述如何使用JavaScript监听文件输入框的变化事件(change事件),并通过遍历文件列表(event.target.files
)来获取每个选中文件的信息。每当用户选择文件后,通过创建动态列表项(<li>
)来展示文件的名称、类型和大小。这交互式的例子通过清晰的HTML结构和JavaScript事件处理,使用户能够轻松选择文件并查看其基本信息。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Information Example</title>
</head>
<body>
<!-- 文件输入框 -->
<input type="file" id="files-list" multiple>
<!-- 显示文件信息的列表 -->
<p>Selected Files Information:</p>
<ul id="file-info-list"></ul>
<script>
// 添加事件监听器,当文件选择发生变化时触发
document.getElementById("files-list").addEventListener("change", (event) => {
const filesList = event.target.files; // 获取选中的文件列表
const fileInfoList = document.getElementById("file-info-list"); // 文件信息列表
// 清空之前的文件信息
fileInfoList.innerHTML = "";
// 遍历选中的每个文件,显示文件信息
for (let i = 0; i < filesList.length; i++) {
const file = filesList[i];
const listItem = document.createElement("li"); // 创建列表项元素
// 显示文件信息(文件名、类型、大小)
listItem.textContent = `${file.name} (${file.type}, ${file.size} bytes)`;
fileInfoList.appendChild(listItem); // 将列表项添加到文件信息列表中
}
});
</script>
</body>
</html>
FileReader
FileReader
类型表示一种异步文件读取机制,可以将其类比于XMLHttpRequest
,但它专门用于从文件系统异步读取文件内容,而非从服务器获取数据。FileReader
类型提供了多个方法,用于实现对文件数据的异步读取操作。
基本语法
js
const reader = new FileReader();
reader.onload = () =>{}
reader.readAsDataURL(file);
方法
- readAsText(file, encoding) 从文件中读取纯文本内容并保存在 result 属性中。第二个参数表示编码,是可选的。
- readAsDataURL(file) 读取文件并将内容的数据 URI 保存在 result 属性中。
- readAsBinaryString(file) 读取文件并将每个字符的二进制数据保存在 result 属性中。
- readAsArrayBuffer(file) 读取文件并将文件内容以 ArrayBuffer 形式保存在 result 属性。
这些读取数据的方法为处理文件数据提供了极大的灵活性。例如,为了向用户显示图片,可以将图片读取为数据 URI,而为了解析文件内容,可以将文件读取为文本。
事件
因为上面的读取方法都是异步的,所以每个 FileReader 都会发布几个事件, 其中三个最有用的事件:
- progress: progress 还有更多数据,每隔 50 毫秒会触发一次
- error: 发生了错误,属性时一个独享,包含 code 1.未找到文件 2.安全错误 3. 读取被中断 4. 文件不可读 5.编码错误
- load: 读取完成,文件成功加载后触发, error事件被处罚,则不会触发load事件。
使用 FileReader 读取图片
简单的Web页面允许用户选择图片文件,通过 FileReader
异步读取图片内容,并在页面上显示图片。同时,添加了一个进度条,展示文件读取的实时进度并监听错误事件。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Read and Display Image</title>
</head>
<body>
<!-- 文件输入框 -->
<input type="file" id="image-input">
<!-- 显示图片 -->
<img id="selected-image" style="max-width: 100%;">
<!-- 进度条 -->
<progress id="file-progress" value="0" max="100"></progress>
<script>
document.getElementById("image-input").addEventListener("change", (event) => {
const selectedImage = document.getElementById("selected-image");
const fileProgress = document.getElementById("file-progress");
const file = event.target.files[0];
if (file && file.type.startsWith("image")) {
// 通过FileReader异步读取文件内容
const reader = new FileReader();
reader.onload = (e) => {
// 将读取的图片数据设置为img元素的src属性,显示在页面上
selectedImage.src = e.target.result;
fileProgress.value = 100; // 读取完成时将进度条设为100%
};
reader.onprogress = (e) => {
if (e.lengthComputable) {
const percentLoaded = (e.loaded / e.total) * 100;
fileProgress.value = percentLoaded; // 更新进度条
}
};
reader.onerror = () => {
alert("文件读取失败。请重新选择有效的图片文件。");
selectedImage.src = ""; // 清空图片显示
};
reader.readAsDataURL(file); // 以DataURL形式读取图片内容
} else {
alert("请选择有效的图片文件。");
selectedImage.src = ""; // 清空图片显示
}
});
</script>
</body>
</html>
FileReaderSync 类型
FileReaderSync 是 FileReader 类型的同步版本。拥有 FileReader 相同的方法。,只有在整个文件都加载到内存之后才会继续执行。
FileReaderSync 只在工作线程(Web Workers)中可用,因为如果读取整个文件耗时太长则会影响全局。
FileReaderSync
是一个同步的API,它主要设计用于在工作线程(Web Workers)中执行,以避免阻塞主线程。在工作线程中使用它时,不会阻塞主进程,因为工作线程是在独立于主线程的线程中运行的。
例子
假设通过 postMessage()向工作线程发送了一个 File 对象。以下代码会让工作线程同步将文件读取到内存中,然后将文件的数据 URL发回来:
js
// worker.js
self.onmessage = (messageEvent) => {
const syncReader = new FileReaderSync();
// 读取文件时阻塞工作线程
const result = syncReader.readAsDataURL(messageEvent.data);
// PDF 文件的示例响应
console.log(result); // data:application/pdf;base64,JVBERi0xLjOK...
// 把URL 发回去
self.postMessage(result);
};
结语
File API 的引入使得在浏览器环境中对客户端文件的操作更加方便和安全。通过 File、FileReader 和 FileReaderSync,开发者可以获取文件信息、异步读取文件内容以及在 Web Workers 中进行同步文件读取,从而实现更多样化的文件交互和处理操作。在实际应用中,开发者可以根据具体需求选择合适的类型和方法,以达到更好的用户体验和性能优化,如果你有独特的见解或者经验,欢迎在下方评论区分享,让大家共同学习进步。