input[type="file"]仅触发选择,上传、校验、预览需js手动实现;value为fakepath是安全策略,应以input.files[0]为准;accept仅为提示性过滤;必须用formdata和filereader,后端校验不可省略。

input[type="file"] 不是“选完就传”,它只负责触发选择——所有上传、校验、预览逻辑都得你手动补全。浏览器故意屏蔽真实路径、不强制类型过滤、不自动提交,这些都不是缺陷,而是安全设计。
为什么 value 总是 C:\fakepath\xxx
这是所有主流浏览器(Chrome、Firefox、Safari、Edge)统一实施的安全策略,不是 bug,也无法绕过。你永远不该读取 input.value 做路径判断或拼接逻辑。
-
input.files[0]才是唯一可信入口:含name、size、type、lastModified - 多选时
input.files.length才反映真实数量,input.value仍只显示第一个文件名 - 用户取消选择后,
input.files.length变为0,但input.value可能残留旧值——必须以files为准
accept 属性到底能限制什么
accept 是提示性过滤,不是强制拦截。用户在文件对话框里切到“所有文件”就能绕过,所以它只降低误选概率,不能替代校验。
- 按 MIME 类型写:
accept="image/png,image/jpeg,application/pdf" - 按扩展名写(注意开头的点):
accept=".png,.jpg,.pdf" - 通配写法:
accept="image/*"(支持所有图片)、accept="video/*" - Safari 对扩展名写法支持弱;iOS 上
accept="image/*"可能同时弹相机和图库,加capture="user"才能锁定前置摄像头
上传前必须做哪些 JavaScript 补位
光有 input type="file" 不会发请求,也不生成可读内容。关键动作必须由 JS 主动触发:
- 读取文件内容(如预览):用
FileReader的readAsDataURL,onload回调里才能拿到reader.result - 构造上传数据:必须用
FormData,fd.append("file", input.files[0]),key 名要和后端约定一致 - 发起请求:用
fetch(fd),不要手动设Content-Typeheader,否则会破坏multipart/form-data的 boundary - 校验不能只靠前端:
file.size和file.type可在客户端快速拦截明显异常,但后端必须重验——恶意用户可轻易伪造 JS 或绕过页面直接发请求
容易被忽略的 DOM 和表单细节
看似简单的控件,实际受 DOM 状态和表单规则强约束:
-
name属性必不可少:没有name,FormData或表单提交时该字段直接消失 - 不能用
display: none或visibility: hidden隐藏控件:部分浏览器拒绝触发选择框 -
required属性只校验是否选中,不校验文件有效性;多选时只要input.files.length > 0就算通过 -
input.files是FileList,不是数组:不能直接用forEach、map或展开运算符,需先转成数组(Array.from(input.files))
真正麻烦的从来不是怎么写 accept 或 multiple,而是忘记 FormData 必须用、FileReader 必须异步处理、以及后端校验不可省略——这三个点漏掉任意一个,上线后基本等于裸奔。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











