浏览器为安全限制input[type="file"]的value显示为C:fakepath...,真实路径需通过input.files[0]获取name、size等属性;accept仅提示过滤,需结合change事件与FileReader读取文件,并做客户端校验。
input[type="file"] 的 value 总是 C:fakepath...
这是浏览器主动做的安全限制,不是 bug。所有主流浏览器(Chrome、Edge、Firefox、Safari)都会屏蔽真实本地路径,只暴露文件名。你无法通过 input.value 获取完整路径,也不该依赖它做任何逻辑判断。
真正可用的文件信息藏在 input.files 这个 FileList 对象里:
input.files[0] 是第一个选中的 File 实例,含 name、size、type、lastModified 等可靠属性multiple),input.files.length 才是实际数量,input.value 仍只显示第一个文件名input.files.length 变为 0,但 input.value 可能还残留旧值——必须以 files 为准accept 真正限制可选文件类型accept 是提示性过滤,不是强制校验。用户仍可通过修改文件对话框的“文件类型”下拉菜单绕过(比如 Chrome 里点“全部文件”)。
有效写法取决于你要匹配的维度:
立即学习“前端免费学习笔记(深入)”;
accept="image/png,image/jpeg" 或 accept="application/pdf"
accept=".png,.jpg,.jpeg"(注意开头的点不能省)accept="image/*"(支持所有图片)、accept="video/*"
accept="image/*,.pdf,application/msword"
⚠️ Safari 对 accept 支持较弱,尤其扩展名写法可能被忽略;移动端 iOS 的 accept="image/*" 有时会同时弹出相机和图库,加 capture="user" 才能强制调用前置摄像头。
不要用 click 或 input 事件监听选择动作——change 才是唯一可靠的时机,且只在用户真正确认选择后触发。
典型读取流程:
change 事件:input.addEventListener('change', handler)
e.target.files 拿到文件列表,检查长度是否 > 0File 实例创建 FileReader 实例readAsText()(文本)、readAsDataURL()(图片预览)、readAsArrayBuffer()(二进制处理)示例:读取首个文件为文本并打印
input.addEventListener('change', e => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = () => console.log(reader.result); reader.readAsText(file);});
前端校验只为提升体验,绝不能替代服务端验证。但以下几项建议在 change 后立刻执行:
files.length 是否为 0(用户点了取消)file,用 file.size 判断是否超限(如 > 5MB),提前提示file.type 或 file.name.split('.').pop().toLowerCase() 做二次类型比对,和 accept 值交叉验证FormData.append('files', file) 中 key 名是否和服务端约定一致(单文件常用 file,多文件建议用 files 并确保后端支持数组解析)容易被忽略的是:即使设置了 required 属性,用户也能绕过(比如禁用 JS 后手动提交),所以表单提交时仍要检查 files.length;另外,File 对象本身不可序列化,别试图把它直接塞进 JSON.stringify。