JavaScript如何从Blob获取上传图片的原始宽高尺寸
图片上传获取原始宽高异常解决方案
问题核心原因
直接读取imageFile宽高返回undefined,是因为File对象只是本地文件的句柄引用,本身不存储图片解码后的像素尺寸信息;读取页面img元素拿到90*90的错误尺寸,是因为取到的是CSS渲染后的布局尺寸,不是图片原始像素值,同时复用受CSS约束的页面img元素作为drawImage的源,会导致canvas只能读到渲染后的低分辨率内容。
可行修复方案
- 读取图片原始尺寸必须用Image元素的
naturalWidth和naturalHeight属性,这两个属性返回值永远对应图片文件的真实像素宽高,完全不受CSS缩放影响。 - 优先创建脱离文档流的临时Image对象解析本地文件,不要直接复用被CSS约束的页面内img元素做源数据读取,避免样式干扰。
- 用
URL.createObjectURL()生成本地文件的Blob引用加载图片,相比FileReader转base64的方案性能更好,处理大尺寸原图时无额外编码开销。 - 用完Blob URL后记得手动调用
URL.revokeObjectURL()释放内存,避免内存泄漏。
修正后可直接运行的代码
let imgInput = document.getElementById('id_photo'); imgInput.addEventListener('change', function (e) { if (!e.target.files) return; for (let i = 0; i < e.target.files.length; i++) { const imageFile = e.target.files[i]; const blobURL = URL.createObjectURL(imageFile); // 创建临时Image对象,不插入DOM,不受页面CSS影响 const tempImg = new Image(); tempImg.onload = function () { // 直接读取原始像素尺寸,不受任何样式干扰 const originWidth = tempImg.naturalWidth; const originHeight = tempImg.naturalHeight; // 基于原始宽高计算缩放后的目标尺寸 const [targetWidth, targetHeight] = resizeImage({ width: originWidth, height: originHeight }); const canvas = document.createElement("canvas"); canvas.width = targetWidth; canvas.height = targetHeight; const ctx = canvas.getContext("2d"); // 用临时Image对象绘制,能拿到完整原始像素 ctx.drawImage(tempImg, 0, 0, targetWidth, targetHeight); // 此处编写转base64、后续业务逻辑 // const resultBase64 = canvas.toDataURL('image/jpeg', 0.9); // 释放Blob URL占用的内存 URL.revokeObjectURL(blobURL); } tempImg.onerror = function () { // 处理图片加载失败场景 URL.revokeObjectURL(blobURL); } tempImg.src = blobURL; } });
补充说明
如果不想创建临时Image对象,坚持复用页面上已有的img元素,只需要在img的onload回调里,把读取尺寸的逻辑改成取img.naturalWidth和img.naturalHeight,drawImage传入的img虽然被CSS缩放,但只要传对原始尺寸对应的目标宽高,canvas依然可以绘制出完整分辨率的内容,不会被CSS渲染尺寸影响。
内容的提问来源于stack exchange,提问作者Mammadali Mammadaliyev
相关产品推荐
相关产品推荐

