Vue应用FormData上传大图片时被JavaScript意外旋转90度问题咨询
大尺寸图片FormData上传时意外旋转90°的问题根源
这个旋转现象不是你手动编写的图片处理逻辑导致的,触发根源和浏览器的大图片解码规则、你代码中冗余的图片加载逻辑直接相关:
核心触发原因
- 所有手机、消费级相机拍摄的照片都会在EXIF元数据中写入
Orientation(方向)标记,记录拍摄时设备的握持角度,比如竖拍照片的该标记值通常为6,代表需要顺时针旋转90°才是符合人眼视觉的正常朝向。 - 你的代码中存在一段完全冗余的逻辑:通过
FileReader把文件转成DataURL,再赋值给new Image()对象加载,但后续流程中完全没有使用这个Image实例做任何预览、裁剪操作。 - 当图片尺寸超过浏览器的内部解码阈值(不同设备阈值不同,通常单边长超过8192px/16384px即触发)时,浏览器在通过Image对象解码图片的过程中,会默认按照EXIF的Orientation标记自动旋转像素数据到正确朝向,同时丢弃原始EXIF方向信息。
- 部分旧版Chrome、iOS Safari、安卓系统Webview存在已知bug:在同一执行上下文中触发上述大图片自动校正流程后,会错误将校正后的像素数据关联到你持有的原始File引用上,最终导致append到FormData中的文件是经过旋转的版本,而非磁盘上存储的原始文件。
补充:你当前代码中还存在一个逻辑bug:this.loading = false写在forEach循环外部,会在所有异步上传任务刚启动、还未执行完成时就关闭加载状态,和旋转问题无关,但会导致加载状态显示异常。
修复方案
- 直接删除冗余的FileReader读取、Image实例加载逻辑:如果不需要做前端图片预览、裁剪等处理,不需要提前解码图片,直接将原始File对象append到FormData中即可,从根源上避免浏览器触发大图片自动校正流程。
- 如果后续需要加图片预览功能,不要依赖浏览器的自动方向校正,要么读取EXIF中的Orientation值在Canvas绘制时手动校正方向,要么给预览img标签添加
image-orientation: from-image样式,让浏览器仅在渲染层做方向校正,不修改原始文件数据。 - 调整loading状态的触发时机,等所有上传任务全部执行完成后再关闭加载状态。
修正后的核心实现代码如下:
uploadFiles(files) { this.validateUploadFiles(files); if( this.uploadErrors?.length ) return; this.loading = true; const timestamp = Date.now(); // 收集所有上传任务Promise const uploadTasks = files.map(async (file, index) => { // 直接使用原始文件构造FormData,移除冗余的图片解码逻辑 const formData = new FormData(); formData.append("file", file); formData.append("index", index); formData.append("timestamp", timestamp); try { const result = await this.$api.media.uploadCampaignPdfExportMedia(this.campaignId, formData); this.uploadSuccess.push(result.data.fileName); } catch (error) { console.log(error); this.uploadErrors.push(this.$t("campaign.upload.error.upload_failed", {name: file.name})); } }); // 所有任务结束后统一关闭loading Promise.all(uploadTasks).finally(() => { this.loading = false; }); },
内容的提问来源于stack exchange,提问作者Čamo
相关产品推荐
相关产品推荐

