
HTML5 的 本身不直接上传文件,它只负责选择文件;上传必须配合 JavaScript(如 fetch 或 XMLHttpRequest)和后端接口才能完成。
没反应或选不了多个文件?常见原因是属性缺失或限制不当:
multiple 属性没加 → 只能选一个文件,加了才支持多选:
accept 写错格式 → 比如想限制图片但写成 accept="image/*"(正确),写成 accept="jpg,png" 就无效(缺少 image/ 前缀)display: none 隐藏后未通过 label 或 JS 触发 click(),会导致实际无法唤起选择框capture 支持较特殊 → capture="camera" 在部分 iOS 版本仅对 image/* 有效,视频需用 video/* 显式声明核心是监听 change 事件,拿到 input.files(FileList 对象),再用 FormData 构造请求体:
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
const files = e.target.files;
if (!files.length) return;
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i]); // 后端接收字段名通常是 'files' 或 'file'
}
try {
const res = await fetch('/upload', {
method: 'POST',
body: formData
});
console.log(await res.json());
} catch (err) {
console.error('上传失败:', err);
}
});
注意:FormData.append() 第二个参数必须是 File 对象(来自 files[i]),不能传路径字符串或 blob.slice() 后未重命名的 Blob。
立即学习“前端免费学习笔记(深入)”;
原生 fetch 不支持上传进度监听,必须换用 XMLHttpRequest;另外服务端超时、Nginx 默认 1MB 上传限制、浏览器内存压力都可能造成失败:
XHR.upload.onprogress 获取进度:xhr.upload.onprogress = (e) => { console.log((e.loaded / e.total * 100).toFixed(1) + '%'); };
busboy,PHP 的 $_FILES 有大小限制)client_max_body_size,例如设为 100m
FileReader.readAsDataURL() 处理 >5MB 文件,改用 readAsArrayBuffer() 或直接 append 到 FormData真正容易被忽略的是:前端校验(如文件类型、大小)只是体验优化,后端必须重新校验;accept 和 type 属性完全可被绕过,用户修改 HTML 或用 curl 就能传任意文件。