仅负责文件选择,不自动上传;必须配合 javascript(如 fetch + formdata)或表单提交(需设 enctype="multipart/form-data")才能上传,且须设 name 属性、避免隐藏失效、正确使用 accept 和 multiple。

file 类型的 <input> 本身不上传文件,它只负责选择文件;真正触发上传必须配合 JavaScript 发起请求(如 fetch)或表单提交(<form enctype="multipart/form-data"></form>)。
为什么点击 <input type="file"> 没反应或选不了文件?
常见原因不是代码写错,而是被隐藏或拦截了默认行为:
- 用了
display: none或visibility: hidden直接隐藏元素 —— 浏览器会禁用其交互,必须用其他方式“伪装”隐藏(比如opacity: 0+ 绝对定位覆盖在按钮上) - 父容器设置了
pointer-events: none,或者有遮罩层挡住了点击区域 - 在移动端,部分 WebView(如微信内置浏览器)对
accept属性校验更严,比如写成accept=".pdf"可能不识别,应改用accept="application/pdf" - 未设置
multiple却想一次选多个,或设了multiple但 JS 里只取了files[0]
如何用 fetch 上传选中的文件(推荐现代做法)?
这是最灵活的方式,能控制进度、取消、错误重试等。关键点是:不能直接把 File 对象当 JSON 发,得用 FormData 包装:
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append('upload', file); // 'upload' 是后端接收的字段名
try {
const res = await fetch('/api/upload', {
method: 'POST',
body: formData, // 不要设 headers,让浏览器自动设 Content-Type(含 boundary)
});
console.log(await res.json());
} catch (err) {
console.error('上传失败', err);
}
});
注意:FormData 会自动处理二进制边界(boundary),手动加 headers: {'Content-Type': 'multipart/form-data'} 反而会出错。
用表单提交时,enctype 忘了设会怎样?
如果 <form></form> 没写 enctype="multipart/form-data",即使 <input type="file"> 选了文件,后端也收不到 —— 浏览器会把文件转成空字符串或直接忽略:
-
accept是提示性属性,不影响实际上传内容,仅过滤文件选择对话框的可选项 - 后端接收字段名(如
avatar)必须和name属性一致 - 服务端框架(如 Express、Django、Spring Boot)通常需要额外中间件(如
multer)解析 multipart 请求
容易被忽略的是:file input 的 files 属性是实时的只读类数组,每次选择都会新建对象;若需长期持有引用(比如预览+上传分离),得立刻用 URL.createObjectURL() 保存预览地址,否则选新文件后旧 File 对象虽仍存在,但用户已无法再通过 input 访问它。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











