Angular表单上传前图片调整大小问题排查及方案需求
Angular图片上传前调整大小功能修复
你的问题核心是图片未加载完成就执行绘制导致功能时好时坏,还有img.onload里this指向错误的问题。下面是修复后的完整实现:
修复后的模板代码
<form [formGroup]="uploadForm" (ngSubmit)="upload()"> <input type="file" id="file" formControlName="file" (change)="onImageChange($event)" accept="image/*"> <div class="contentMainInput" *ngIf="imgFile"> <img [src]="imgFile" style="height:100px"> </div> <button type="submit" [disabled]='!uploadForm.valid'>Upload</button> </form>
修复后的组件TS代码
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-image-upload', templateUrl: './image-upload.component.html', styleUrls: ['./image-upload.component.css'] }) export class ImageUploadComponent implements OnInit { uploadForm!: FormGroup; imgFile: string | null = null; dataUrl: string | null = null; constructor(private fb: FormBuilder) {} ngOnInit(): void { this.uploadForm = this.fb.group({ file: [null, Validators.required], imgSrc: [null] }); } onImageChange(e: Event): void { const target = e.target as HTMLInputElement; if (target.files && target.files.length > 0) { const imgFile = target.files[0]; // 用URL.createObjectURL代替FileReader,更高效 const imgUrl = URL.createObjectURL(imgFile); const img = document.createElement('img'); img.src = imgUrl; // 用箭头函数保证this指向组件实例 img.onload = () => { // 释放URL对象,避免内存泄漏 URL.revokeObjectURL(imgUrl); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (!ctx) return; // 设置画布大小为100x100 canvas.width = 100; canvas.height = 100; // 绘制并调整图片大小 ctx.drawImage(img, 0, 0, 100, 100); // 转成jpeg格式的dataUrl this.dataUrl = canvas.toDataURL('image/jpeg', 0.9); this.imgFile = this.dataUrl; // 更新表单控件 this.uploadForm.patchValue({ imgSrc: this.dataUrl }); }; } } upload(): void { if (this.uploadForm.invalid || !this.dataUrl) return; // 将dataUrl转成Blob用于上传 const blob = this.dataUrlToBlob(this.dataUrl); const formData = new FormData(); formData.append('resizedImage', blob, 'resized-image.jpg'); // 这里调用你的上传API // this.http.post('/api/upload', formData).subscribe(...); console.log('准备上传调整后的图片:', blob); } // 辅助方法:将dataUrl转成Blob private dataUrlToBlob(dataUrl: string): Blob { const arr = dataUrl.split(','); const mime = arr[0].match(/:(.*?);/)![1]; const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); } }
关键修改说明
- 图片加载完成后再处理:把画布绘制、表单赋值逻辑全部放到
img.onload回调里,确保图片完全加载后才执行调整大小操作,解决时好时坏的问题。 - 正确的this指向:使用箭头函数
img.onload = () => {},保证回调里的this指向组件实例,这样就能正常访问uploadForm、imgFile等属性。 - 优化URL处理:用
URL.createObjectURL代替FileReader,更高效且避免不必要的异步读取;同时记得用URL.revokeObjectURL释放资源,防止内存泄漏。 - 完善上传逻辑:添加了
dataUrlToBlob方法,把调整后的dataUrl转成Blob对象,符合大多数后端的文件上传要求。
内容的提问来源于stack exchange,提问作者Ezo
相关产品推荐
相关产品推荐

