传统的文件上传控件(<input type="file">)功能有限,用户体验不佳,无法满足现代 Web 应用的需求。幸运的是,HTML5 提供了强大的 File API,它允许 JavaScript 在客户端读取和操作本地文件,极大地丰富了文件处理的能力。本文将详细介绍 File API 的核心组件和使用方法,帮助你更好地理解和应用这一强大的工具。
一、File API 简介
HTML5 的 File API 提供了一组接口,允许 JavaScript 在客户端读取和操作本地文件。这些接口包括:
- File:表示单个文件,提供了文件的基本信息,如文件名、大小、类型等。
- FileList:一个类数组对象,包含多个 File 对象,通常用于处理多文件上传。
- FileReader:用于异步读取文件内容,支持多种格式,如文本、二进制、Data URL 等。
- Blob:表示二进制数据,File 对象继承自 Blob,因此可以使用 Blob 的方法和属性。
File API 的出现,使得开发者能够在客户端对文件进行预处理,如验证文件类型、大小,甚至读取文件内容,从而提升用户体验并减轻服务器负担。
二、File 对象
(一)构造函数
File 对象可以通过构造函数创建,通常用于生成新的文件对象。构造函数的语法如下:
new File(array, name, [options]);
- array:一个数组,包含文件的内容,可以是字符串或二进制数据。
- name:文件名或路径。
- options:可选参数,用于设置文件的 MIME 类型和最后修改时间。
例如,创建一个简单的文本文件:
const file = new File(["Hello, world!"], "hello.txt", {
type: "text/plain",
});
(二)实例属性和方法
File 对象继承自 Blob,因此具有以下实例属性:
- File.lastModified:文件最后修改的时间戳。
- File.name:文件名。
- File.size:文件大小,以字节为单位。
- File.type:文件的 MIME 类型。
File 对象没有自己的实例方法,但可以使用 Blob 的方法,如 slice()。
三、FileList 对象
FileList 对象是一个类数组对象,包含多个 File 对象。它通常出现在以下两个场景中:
- 文件上传控件(
<input type="file">)的files属性。 - 拖拽文件时,
DataTransfer.files属性。
例如:
<input type="file" id="file" multiple>
const input = document.getElementById("file");
input.onchange = (event) => {
const files = event.target.files; // FileList 对象
console.log(files);
};
FileList 对象具有以下属性和方法:
- length:返回 FileList 中的文件数量。
- item(index):返回指定索引的 File 对象。
由于 FileList 是类数组对象,可以直接使用方括号访问文件,例如 files[0]。
四、FileReader 对象
FileReader 对象用于异步读取文件内容。它提供了多种方法来读取文件,支持文本、二进制和 Data URL 格式。FileReader 的构造函数如下:
const reader = new FileReader();
(一)实例属性
FileReader 提供了以下实例属性:
- FileReader.error:读取文件时产生的错误对象。
- FileReader.readyState:读取文件时的当前状态(0:未加载,1:加载中,2:加载完成)。
- FileReader.result:读取完成后的文件内容,可能是字符串或 ArrayBuffer。
- FileReader.onabort、onerror、onload、onloadstart、onloadend、onprogress:事件监听函数,用于处理读取过程中的各种事件。
(二)实例方法
FileReader 提供了以下实例方法:
- FileReader.abort():终止读取操作。
- FileReader.readAsArrayBuffer(blob):以 ArrayBuffer 格式读取文件。
- FileReader.readAsBinaryString(blob):以二进制字符串格式读取文件。
- FileReader.readAsDataURL(blob):以 Data URL 格式读取文件。
- FileReader.readAsText(blob, encoding):以文本格式读取文件。
例如,读取文本文件:
<input type="file" id="file">
const input = document.getElementById("file");
input.onchange = (event) => {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = (event) => {
console.log(event.target.result); // 文件内容
};
reader.readAsText(file);
};
五、综合实例:文件预览与上传
以下是一个综合实例,展示如何使用 File API 实现文件预览和上传功能。
(一)HTML
<label>
<input type="file" id="file" multiple>
<div class="uploadImg">
<div class="cross"></div>
</div>
</label>
(二)CSS
.uploadImg {
width: 150px;
height: 150px;
border: 1px dashed skyblue;
border-radius: 30px;
position: relative;
cursor: pointer;
}
.cross {
width: 30px;
height: 30px;
position: absolute;
left: calc(50% - 15px);
top: calc(50% - 15px);
}
.cross::before {
content: "";
width: 30px;
height: 2px;
background-color: skyblue;
position: absolute;
top: calc(50% - 1px);
}
.cross::after {
content: "";
width: 30px;
height: 2px;
background-color: skyblue;
position: absolute;
left: calc(50% - 15px);
top: calc(50% - 1px);
transform: rotate(90deg);
}
input[type="file"] {
display: none;
}
(三)JavaScript
const fileInput = document.getElementById("file");
const uploadImg = document.querySelector(".uploadImg");
const cross = document.querySelector(".cross");
fileInput.onchange = () => {
const files = fileInput.files;
const reader = new FileReader();
if (files.length > 0) {
reader.readAsDataURL(files[0]);
}
reader.onload = () => {
uploadImg.style.background = `url(${reader.result}) center/cover no-repeat`;
cross.style.opacity = 0;
};
};
在这个示例中,用户选择文件后,文件内容将被读取并显示为背景图像,同时隐藏上传图标。
六、File System Access API:面向未来的文件操作
虽然 File API 提供了强大的文件读取功能,但它主要关注文件的读取,而不是文件的存储。为了满足离线存储的需求,W3C 推出了 File System Access API,它允许 Web 应用程序直接与本地文件系统交互,提供更完整的文件操作能力。
File System Access API 提供了以下功能:
- 打开文件:允许用户选择本地文件并读取内容。
- 保存文件:允许用户将文件保存到本地。
- 编辑文件:允许用户在本地编辑文件。
目前,File System Access API 仍处于实验阶段,仅在 Chrome 浏览器中得到支持。