MDN Web API 文件操作指南:在网页应用中处理本地文件
2025-07-07 00:50:28作者:丁柯新Fawn
前言
在现代网页应用中,处理用户本地文件是一个常见需求。MDN Web API 提供了完整的文件操作接口,让开发者能够安全地访问用户选择的文件内容。本文将全面介绍如何使用这些 API 实现文件选择、预览和上传等功能。
基础文件选择
通过 input 元素获取文件
最简单的文件选择方式是使用 HTML 的 <input type="file">
元素:
<input type="file" id="fileInput" multiple>
通过 JavaScript 可以访问用户选择的文件:
const fileInput = document.getElementById('fileInput');
const selectedFiles = fileInput.files; // 获取 FileList 对象
multiple
属性允许用户选择多个文件。每个文件都是一个 File
对象,包含以下重要属性:
name
: 文件名(不包含路径)size
: 文件大小(字节)type
: 文件 MIME 类型
监听文件选择变化
可以监听 input 元素的 change 事件来实时获取文件:
fileInput.addEventListener('change', function(e) {
const files = e.target.files;
// 处理文件...
});
文件信息展示
计算文件总大小
以下示例展示如何计算并格式化多个文件的总大小:
function formatFileSize(bytes) {
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let unitIndex = 0;
while (bytes >= 1024 && unitIndex < units.length - 1) {
bytes /= 1024;
unitIndex++;
}
return `${bytes.toFixed(2)} ${units[unitIndex]}`;
}
const totalSize = Array.from(selectedFiles)
.reduce((sum, file) => sum + file.size, 0);
console.log(`总大小: ${formatFileSize(totalSize)}`);
优化用户体验
自定义文件选择按钮
原生文件选择控件样式受限,可以通过以下方式美化:
<button id="customButton">选择文件</button>
<input type="file" id="hiddenInput" style="display:none">
<script>
document.getElementById('customButton').addEventListener('click', () => {
document.getElementById('hiddenInput').click();
});
</script>
无障碍文件选择
对于无障碍访问,推荐使用 label 元素关联隐藏的 input:
<input type="file" id="fileInput" class="visually-hidden">
<label for="fileInput" class="custom-file-button">选择文件</label>
<style>
.visually-hidden {
position: absolute;
clip: rect(0 0 0 0);
width: 1px;
height: 1px;
margin: -1px;
}
.custom-file-button {
/* 自定义按钮样式 */
}
</style>
拖放文件操作
现代浏览器支持通过拖放 API 获取文件:
const dropZone = document.getElementById('dropZone');
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
e.stopPropagation();
dropZone.classList.add('dragover');
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
e.stopPropagation();
dropZone.classList.remove('dragover');
const files = e.dataTransfer.files;
// 处理拖放的文件...
});
文件预览技术
图片预览实现
使用 FileReader API 可以实现图片预览:
function previewImage(file) {
const reader = new FileReader();
reader.onload = function(e) {
const img = document.createElement('img');
img.src = e.target.result;
document.body.appendChild(img);
};
reader.readAsDataURL(file);
}
更高效的 Object URL 方案
对于大型文件,使用 Object URL 更高效:
function previewImage(file) {
const img = document.createElement('img');
img.src = URL.createObjectURL(file);
img.onload = function() {
URL.revokeObjectURL(this.src); // 释放内存
};
document.body.appendChild(img);
}
文件上传实践
基础文件上传
使用 XMLHttpRequest 上传文件:
function uploadFile(file) {
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('file', file);
xhr.open('POST', '/upload', true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
console.log(`${percent}% 已上传`);
}
};
xhr.onload = function() {
if (xhr.status === 200) {
console.log('上传成功');
}
};
xhr.send(formData);
}
多文件上传队列
实现带进度显示的多文件上传:
class UploadQueue {
constructor() {
this.queue = [];
this.activeUploads = 0;
this.maxConcurrent = 3;
}
add(file) {
this.queue.push(file);
this.processQueue();
}
processQueue() {
while (this.activeUploads < this.maxConcurrent && this.queue.length) {
const file = this.queue.shift();
this.upload(file);
this.activeUploads++;
}
}
upload(file) {
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('file', file);
xhr.open('POST', '/upload', true);
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
this.updateProgress(file, percent);
}
};
xhr.onload = () => {
this.activeUploads--;
this.processQueue();
};
xhr.send(formData);
}
updateProgress(file, percent) {
console.log(`${file.name}: ${percent}%`);
}
}
安全注意事项
- 始终验证文件类型,不要仅依赖文件扩展名或 MIME 类型
- 对上传文件大小设置合理限制
- 在服务器端进行二次验证
- 处理上传错误和中断情况
- 考虑使用 CSP 增加安全性
总结
MDN Web API 提供了完整的文件操作解决方案,从基础的文件选择到高级的拖放操作和上传管理。通过合理利用这些 API,开发者可以创建功能丰富且用户友好的文件处理功能。记住始终考虑性能和安全性,特别是在处理大型文件或多文件上传时。