图片原始尺寸需在 load 事件后读取 naturalwidth/naturalheight;应创建 image 实例,用 url.createobjecturl 设置 src,监听 onload 获取真实像素,并及时释放内存;需处理 onerror,避免状态污染;校验应按业务场景结构化判断最小/最大尺寸及宽高比。

图片原始尺寸必须等 load 事件后读取 naturalWidth 和 naturalHeight
直接访问 img.width 或 img.height 拿到的不是真实像素尺寸,可能是 0、CSS 设置值或浏览器默认值。因为 DOM 加载时图片还没解码完成,元数据不可用。
正确做法是创建 Image 实例,监听 onload,再读取 naturalWidth/naturalHeight:
const img = new Image();
img.src = URL.createObjectURL(file);
img.onload = () => {
console.log(img.naturalWidth, img.naturalHeight); // ✅ 原始宽高
URL.revokeObjectURL(img.src); // 及时释放内存
};
- 必须用
URL.createObjectURL(file)而非直接设src=file,否则会触发跨域或解析失败 -
onerror必须处理:用户可能选了损坏图、SVG(部分老浏览器不支持 SVG 的 natural 尺寸)、或非图像二进制文件 - 不要缓存
img实例到全局,每次校验都新建,避免状态污染
校验逻辑要分场景写,不能只比固定数值
业务需求不同,校验方式差异很大:头像要正方形且最小 200×200,横幅图要求宽 ≥920 且高 ≥300,封面图则需严格 16:9 比例。硬编码 if (w !== 800 || h !== 600) 会误杀合法图。
推荐结构化判断:
- 最小尺寸:检查
w >= minWidth && h >= minHeight - 最大尺寸:检查
w - 比例容差:用
Math.abs(w / h - targetRatio) ,避免浮点误差和压缩导致的微小偏差 - 是否允许拉伸:若后端会重裁,前端只需保“不低于”;若前端预览即最终展示,还需加
aspect-ratioCSS 强制约束
FileReader 不是必须的,但能提前拦截无效文件
如果仅校验尺寸,Image + onload 足够。但某些场景下你希望在解码前就拒绝明显异常的文件——比如用户上传了一个 5MB 的「图片」,但实际是 PDF 或 ZIP,浏览器仍会尝试解码并卡住 UI。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
此时可用 FileReader 读取文件头魔数(magic number)快速识别真伪:
- JPEG 开头是
FF D8 FF - PNG 是
89 50 4E 47 - GIF 是
47 49 46 38
读前 4 字节即可判断,比完整加载快得多。不过注意:FileReader 是异步的,需与 Image 校验串行或并行协调,别让错误提示错乱。
移动端和 WebView 容易踩的坑
安卓某些 WebView(尤其旧版 QQ 内置浏览器)中,Image.onload 可能不触发,或 naturalWidth 恒为 0;iOS Safari 在低内存时会延迟触发甚至丢弃事件。
应对策略:
- 加超时兜底:
setTimeout(() => { if (!loaded) reject('尺寸检测超时'); }, 5000) - 降级 fallback:超时后尝试用
file.name后缀 +file.size组合粗略判断(如.png文件却只有 1KB,大概率无效) - 禁用
object-fit: cover类样式做预览,它会让缩放后的尺寸干扰判断;预览图务必设width: auto; height: auto;并包裹在固定容器内
最麻烦的是:有些 CMS 导出图或微信转发图的 EXIF 已被剥离,naturalWidth 返回异常值,这时必须靠服务端二次校验兜底——前端尺寸校验永远只是第一道筛子,不是最终判决。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










