You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 });
  }
}

关键修改说明

  1. 图片加载完成后再处理:把画布绘制、表单赋值逻辑全部放到img.onload回调里,确保图片完全加载后才执行调整大小操作,解决时好时坏的问题。
  2. 正确的this指向:使用箭头函数img.onload = () => {},保证回调里的this指向组件实例,这样就能正常访问uploadForm、imgFile等属性。
  3. 优化URL处理:用URL.createObjectURL代替FileReader,更高效且避免不必要的异步读取;同时记得用URL.revokeObjectURL释放资源,防止内存泄漏。
  4. 完善上传逻辑:添加了dataUrlToBlob方法,把调整后的dataUrl转成Blob对象,符合大多数后端的文件上传要求。

内容的提问来源于stack exchange,提问作者Ezo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:15:27