浏览器禁止直接拼接file.value路径预览,因file.value仅为伪造路径;应使用URL.createObjectURL()生成临时内存URL,并及时revoke释放,避免内存泄漏;需校验files.length和type,iOS Safari中video需手动load()。

为什么不能直接用 file.value 拼接本地路径预览
浏览器出于安全限制,完全屏蔽了对本地文件系统路径的访问。你看到的 file.value 只是伪造的文件名(如 C:\fakepath\avatar.jpg),实际路径不可读、不可拼接、也不能用于 src。试图写 img.src = 'file://' + file.value 会直接失败,控制台报错 Not allowed to load local resource。
URL.createObjectURL() 是图片/视频预览的首选方案
对 image/*、video/*、audio/* 类型文件,应优先用 URL.createObjectURL(file),而不是 FileReader.readAsDataURL()。前者是内存引用,不转码、不阻塞主线程、支持流式加载;后者会把整个文件转成 base64 字符串,大图(比如 5MB)会导致明显卡顿甚至内存溢出。
务必注意清理:
- 每次调用后,必须在不需要时手动调用
URL.revokeObjectURL(url),否则对象长期驻留内存,造成泄漏 - 该 URL 只在当前页面生命周期有效,不能存到 localStorage 或传给后端
- 若预览区域复用同一个
<img>元素,记得先revoke旧 URL,再设置新 URL
监听 change 事件时必须校验 files.length
用户点击「取消」或清空选择后,event.target.files 是一个空 FileList,files[0] 为 undefined。直接取值会触发 Cannot read property 'type' of undefined 错误。
立即学习“前端免费学习笔记(深入)”;
正确做法是:
- 先判断
if (e.target.files.length === 0) return - 再检查
file.type.startsWith('image/')或正则匹配扩展名,因为accept="image/*"可被绕过(比如改后缀名) - 如果要支持多图预览,遍历
files数组,但注意单个URL.createObjectURL()对应一个File实例,别重复用同一个 URL 赋多个src
iOS Safari 下 video 预览需额外触发 load()
在 iOS Safari 中,给 <video> 的 src 设置 URL.createObjectURL(file) 后,元数据(尺寸、时长)可能不会自动加载,导致 video.videoWidth 为 0 或播放控件异常。此时需手动调用:
video.src = url;
video.load(); // 强制加载元数据
video.play().catch(() => {}); // 静音自动播放需用户手势后才允许
这个细节容易被忽略,尤其在做响应式头像+封面图+视频混合预览时,只处理了 <img> 却忘了 <video> 的兼容性补丁。



















