pin_drop当前位置:知识文库 ❯ 图文
HTML5 API:HTML5 File API - 完整教程与代码示例
一、教程简介
File API 是 HTML5 提供的一组用于在客户端处理文件信息的接口,允许 Web 应用读取文件的元数据(名称、大小、类型、修改时间等),而无需将文件上传到服务器。File API 通常与 <input type="file"> 元素和拖放(Drag and Drop)API 配合使用,是构建文件上传、文件预览等功能的底层基础。
二、核心概念
File 对象
File 对象继承自 Blob,包含文件的元数据信息:
获取 File 对象的方式
-
通过
<input>元素:input.files返回 FileList -
通过拖放:
dataTransfer.files返回 FileList -
通过 File 构造函数:
new File(bits, name, options)
FileList 与 File
代码示例
// FileList 是类数组对象
const fileList = input.files;
fileList.length; // 文件数量
fileList[0]; // 第一个 File 对象
fileList.item(0); // 同上
// 遍历
for (let i = 0; i < fileList.length; i++) {
const file = fileList[i];
console.log(file.name, file.size, file.type);
}Blob 与 File 的关系
代码示例
Blob(原始二进制数据)
└── File(Blob + 文件元数据)
├── name
├── lastModified
└── 继承 Blob 的方法
├── slice()
├── stream()
├── text()
└── arrayBuffer()三、语法与用法
通过 input 获取文件
代码示例
<input type="file" id="fileInput" multiple>代码示例
const input = document.getElementById('fileInput');
input.addEventListener('change', function(e) {
const files = e.target.files;
for (const file of files) {
console.log('文件名:', file.name);
console.log('大小:', file.size, '字节');
console.log('类型:', file.type);
console.log('修改时间:', new Date(file.lastModified));
}
});通过拖放获取文件
代码示例
dropZone.addEventListener('drop', function(e) {
e.preventDefault();
const files = e.dataTransfer.files;
// 处理文件...
});File 构造函数
代码示例
const file = new File(['Hello, World!'], 'hello.txt', {
type: 'text/plain',
lastModified: Date.now()
});Blob 的 slice 方法
代码示例
// 分片读取大文件
const chunk = file.slice(start, end, contentType);accept 属性限制文件类型
代码示例
<!-- 只接受图片 -->
<input type="file" accept="image/*">
<!-- 只接受 PDF -->
<input type="file" accept=".pdf,application/pdf">
<!-- 接受图片和 PDF -->
<input type="file" accept="image/*,.pdf">
<!-- 多选 -->
<input type="file" multiple accept="image/*">四、代码示例
示例一:文件信息查看器
以下示例展示如何使用 File API 获取文件元数据并展示:
代码示例
// 获取文件信息
function handleFiles(files) {
const fileArray = Array.from(files);
// 汇总信息
const totalCount = fileArray.length;
const totalSize = fileArray.reduce((s, f) => s + f.size, 0);
// 遍历文件
fileArray.forEach(function(file) {
console.log('文件名:', file.name);
console.log('大小:', formatSize(file.size));
console.log('类型:', file.type || '未知');
console.log('修改时间:', new Date(file.lastModified));
});
}
// 格式化文件大小
function formatSize(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}示例二:文件分片上传模拟
代码示例
const CHUNK_SIZE = 1024 * 1024; // 1MB
async function uploadFile(file) {
const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
for (let i = 0; i < totalChunks; i++) {
const start = i * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, file.size);
const chunk = file.slice(start, end);
// 上传分片
await uploadChunk(chunk, i);
// 更新进度
const percent = Math.round((i + 1) / totalChunks * 100);
console.log('上传进度:', percent + '%');
}
}
async function uploadChunk(chunk, index) {
// 模拟上传
await new Promise(resolve => setTimeout(resolve, 300));
console.log('分片', index + 1, '上传完成');
}五、浏览器兼容性
六、注意事项与最佳实践
1. 文件大小验证
代码示例
input.addEventListener('change', function(e) {
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
for (const file of e.target.files) {
if (file.size > MAX_SIZE) {
alert(file.name + ' 超过 10MB 限制');
return;
}
}
});2. 文件类型验证
代码示例
function validateFileType(file, allowedTypes) {
return allowedTypes.some(type => {
if (type.endsWith('/*')) {
return file.type.startsWith(type.replace('/*', '/'));
}
return file.type === type || file.name.endsWith(type);
});
}
// 使用
const allowed = ['image/*', '.pdf', 'text/plain'];
if (!validateFileType(file, allowed)) {
alert('不支持的文件类型');
}3. 安全注意事项
-
不要信任客户端验证:服务端必须再次验证文件类型和大小
-
注意文件名安全:文件名可能包含特殊字符或路径遍历攻击
-
限制文件数量:防止用户选择过多文件
4. 大文件处理
代码示例
// 使用 slice 分片处理大文件
function processLargeFile(file, chunkSize = 1024 * 1024) {
const totalChunks = Math.ceil(file.size / chunkSize);
let currentChunk = 0;
function processNext() {
if (currentChunk >= totalChunks) {
console.log('处理完成');
return;
}
const start = currentChunk * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
// 处理当前分片
processChunk(chunk, currentChunk).then(() => {
currentChunk++;
processNext();
});
}
processNext();
}七、代码规范示例
代码示例
// 推荐:封装文件工具类
class FileUtils {
// 格式化文件大小
static formatSize(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// 获取文件扩展名
static getExtension(filename) {
const parts = filename.split('.');
return parts.length > 1 ? parts.pop().toLowerCase() : '';
}
// 验证文件类型
static isType(file, types) {
return types.some(type => {
if (type.endsWith('/*')) {
return file.type.startsWith(type.slice(0, -1));
}
if (type.startsWith('.')) {
return FileUtils.getExtension(file.name) === type.slice(1);
}
return file.type === type;
});
}
// 验证文件大小
static isWithinSize(file, maxSize) {
return file.size <= maxSize;
}
}
// 使用示例
input.addEventListener('change', function(e) {
const file = e.target.files[0];
if (!FileUtils.isType(file, ['image/*', '.pdf'])) {
alert('仅支持图片和 PDF');
return;
}
if (!FileUtils.isWithinSize(file, 10 * 1024 * 1024)) {
alert('文件不能超过 10MB');
return;
}
console.log('文件信息:', file.name, FileUtils.formatSize(file.size));
});八、常见问题与解决方案
常见问题
如何获取文件夹中的所有文件?
使用 webkitdirectory 属性可以选择整个文件夹,但这是非标准属性,兼容性有限。示例:<input type="file" webkitdirectory>
如何重置 file input?
通过设置 input.value = '' 可以重置文件输入,允许用户再次选择相同的文件。
File 对象可以在不同页面间传递吗?
File 对象不能通过 postMessage 传递给其他窗口(包括 iframe),但可以通过结构化克隆在 Worker 间传递。
如何判断文件是否为图片?
可以通过检查 MIME 类型或文件扩展名来判断:file.type.startsWith('image/') 或使用正则表达式匹配扩展名。
九、总结
File API 提供了在客户端获取文件元数据的能力,通过 <input type="file"> 和拖放操作获取 File 对象,可以读取文件名、大小、类型、修改时间等信息。结合 Blob 的 slice 方法可以实现大文件分片处理。使用时需注意客户端验证不可替代服务端验证、大文件分片处理、文件类型和大小限制等最佳实践。File API 是文件上传、文件预览等功能的底层基础,通常与 FileReader API 配合使用来读取文件内容。
本文涉及AI创作
内容由AI创作,请仔细甄别