是浏览器原生文件选择入口,需配合 name 属性、enctype="multipart/form-data" 表单或 javascript 的 formdata 才能上传;accept 和 multiple 仅作前端提示,服务端必须校验;文件先存临时路径,需后端移动。

用 <input type="file"> 启动文件选择流程
浏览器原生支持文件上传的入口就是 <input type="file">。它不直接上传,只负责唤起系统选择器并提供文件元数据。必须配合表单提交或 JavaScript 才能真正发送到服务器。
常见错误是只写 <input type="file"> 却没加 name 属性——后端收不到字段名,无法解析文件。另外,multiple 和 accept 是实用但非强制的属性:
-
multiple:允许选多个文件,event.target.files返回FileList而非单个File -
accept="image/*"或accept=".pdf,.docx"仅过滤选择器界面,不能替代服务端校验 - 不要依赖
accept防止用户上传恶意类型,它完全可被绕过
表单必须设 enctype="multipart/form-data"
这是最容易漏掉的关键点。默认表单编码是 application/x-www-form-urlencoded,它会把文件转成乱码字符串甚至直接丢弃。不加这个属性,<input type="file"> 就形同虚设。
正确写法示例:
注意:enctype 只对 POST 有效;GET 表单根本不能传文件。
用 JavaScript 拦截上传并自定义处理
如果不想整页跳转、需要进度条或预览,就得用 FormData + fetch 或 XMLHttpRequest。
关键步骤:
- 监听
input事件(不是change,后者在取消选择时可能不触发) - 从
event.target.files取File对象,直接 append 到FormData实例里 -
FormData不需要手动设Content-Type头,浏览器会自动设置带 boundary 的multipart/form-data - 服务端收到的是标准 multipart body,和表单提交完全一致,无需额外适配
简例:
const input = document.querySelector('input[type="file"]');
input.addEventListener('input', (e) => {
const file = e.target.files[0];
const formData = new FormData();
formData.append('document', file); // 'document' 要和服务端约定的字段名一致
fetch('/api/upload', { method: 'POST', body: formData });
});
服务端接收时注意文件大小与临时路径
前端限制(如 input 的 max 属性)纯属装饰,真正卡住上传靠服务端配置。
典型问题:
- Node.js 的
express默认不解析multipart,需用multer等中间件;multer.diskStorage()控制保存路径,limits.fileSize控制单文件上限 - PHP 的
upload_max_filesize和post_max_size必须同时调大,且后者要 ≥ 前者 + 其他表单字段开销 - Python Flask 默认不处理 multipart,要用
request.files.get('xxx'),且MAX_CONTENT_LENGTH要提前设好
文件不会直接存到你指定的最终路径,而是先落盘到临时目录(如 Linux 的 /tmp),再由框架移动。别假设上传完文件就“已经在目标位置”了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











