必须设置enctype="multipart/form-data",否则后端仅收到空字段或文件名字符串;form需method="post",input需name属性与后端字段名一致,required确保提交前已选文件,多文件加multiple属性。

直接用 <input type="file"> + 表单提交,5 行 HTML 就能跑通,但必须加 enctype="multipart/form-data",否则后端收不到文件内容。
最简可用的表单写法
不用 JS、不依赖后端框架,只要服务端有个接收接口(比如 /upload),下面这段就能上传单个文件:
关键点:
-
enctype="multipart/form-data"缺失 → 后端只收到空字段或文件名字符串,不是二进制数据 -
name="file"必须和后端约定一致(如 Flask 用request.files['file'],Node.js 的 multer 配single('file')) -
required只在表单 submit 时生效,且需在<form></form>内才起作用 - 浏览器会跳转或刷新页面,适合传统多页应用;SPA 场景请改用 fetch
想支持多文件?加一个属性就行
把 <input type="file"> 改成:
<input type="file" name="files" multiple>
注意:name 建议用复数形式(如 files),后端解析时更直观;但实际是否支持多文件上传,取决于后端代码逻辑(例如 Flask 需用 request.files.getlist('files'))。
常见坑:
- Chrome/Safari 对
multiple的行为略有差异:Safari 在某些版本下可能仍只允许选一个,除非用户按住 Cmd/Ctrl 多选 - 如果后端只处理
request.files['files'](单值取法),即使前端传了多个,也只会拿到第一个 - 不要给
multiple输入框设accept后再用 JS 读files.length判断 —— 用户可能取消选择,files是空的,但 input.value 不一定清空
为什么不能直接 fetch(File)?
写成 fetch('/upload', { method: 'POST', body: file }) 会报错:TypeError: Request with GET/HEAD method cannot have body 或 Failed to execute 'fetch': Request with GET/HEAD method cannot have body。
原因很实在:
-
File对象不能直接当body发送,fetch 要求 body 是FormData、Blob、URLSearchParams等可序列化类型 - 必须用
new FormData()包一层,再.append('file', file) - 千万别手动设置
Content-Typeheader ——FormData会自动生成带boundary的multipart/form-data,手设就破坏格式,后端直接解析失败
样式丑?隐藏原生控件再绑定点击
原生 <input type="file"> 样式不可靠,::file-selector-button 在 Safari 上基本不生效。稳妥做法是隐藏它,用自定义按钮触发 click:
<input type="file" id="real-file" style="display:none"><button onclick="document.getElementById('real-file').click()">选择文件</button>
然后监听 change 事件更新 UI:
document.getElementById('real-file').addEventListener('change', e => {
const files = e.target.files;
console.log(files.length, '个文件已选');
});
容易忽略的细节:
- 调用
.click()在 iOS Safari 中可能被拦截(尤其非用户手势触发),所以按钮必须是真实点击目标,不能靠 JS 自动触发 - 选完文件后,
input.value是路径伪字符串(如C:\fakepath\abc.pdf),不要拿它做校验或显示,用files[0].name才可靠 - 如果要限制类型,
accept=".pdf,.docx"比accept="application/pdf"兼容性更好,部分浏览器对 MIME 类型识别不准
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











