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

Angular14文件上传组件:单文件上传取消功能实现问题求助

Angular 14 文件上传取消功能修正与优化

一、this.req is not defined 错误修复

问题出在你用全局的this.req存储所有请求订阅——一是这个变量没正确初始化,二是多个请求会覆盖同一变量,导致作用域混乱。正确的思路是给每个文件单独绑定对应的请求订阅。

1. 重构文件存储数组

把原来的droppedFilesArray从单纯的File[]改成包含文件、订阅对象、上传状态的对象数组,方便跟踪每个文件的上传情况:

// 组件内定义
droppedFilesArray: Array<{
  file: File;
  uploadSub?: Subscription;
  progress: number;
  status: 'pending' | 'uploading' | 'completed' | 'cancelled' | 'failed';
}> = [];

2. 单个文件上传逻辑

写一个独立的上传方法,为每个文件创建HTTP请求,并把订阅对象存在对应文件项里:

import { HttpClient, HttpEvent, HttpEventType } from '@angular/common/http';
import { Subscription } from 'rxjs';

constructor(private http: HttpClient) {}

startSingleUpload(fileItem: any) {
  const formData = new FormData();
  formData.append('file', fileItem.file);

  // 创建上传请求Observable
  const upload$ = this.http.post('/your-upload-api', formData, {
    reportProgress: true,
    observe: 'events' // 监听上传进度事件
  });

  // 订阅请求并保存订阅对象
  fileItem.uploadSub = upload$.subscribe(
    (event: HttpEvent<any>) => {
      if (event.type === HttpEventType.UploadProgress) {
        // 计算进度百分比
        fileItem.progress = Math.round((100 * event.loaded) / (event.total || 1));
      } else if (event.type === HttpEventType.Response) {
        fileItem.status = 'completed';
      }
    },
    (err) => {
      fileItem.status = 'failed';
      console.error('上传失败:', err);
    }
  );

  fileItem.status = 'uploading';
}

3. 取消单个上传的方法

点击叉号时,调用这个方法取消对应文件的请求:

cancelSingleUpload(fileItem: any) {
  if (fileItem.uploadSub && !fileItem.uploadSub.closed) {
    fileItem.uploadSub.unsubscribe();
    fileItem.status = 'cancelled';
    // 可选:把已取消的文件从列表里移除
    // const idx = this.droppedFilesArray.indexOf(fileItem);
    // if (idx !== -1) this.droppedFilesArray.splice(idx, 1);
  }
}

4. 批量发起上传

遍历数组,给每个待上传的文件启动请求:

startAllUploads() {
  this.droppedFilesArray.forEach(item => {
    if (item.status === 'pending') {
      this.startSingleUpload(item);
    }
  });
}

5. 模板绑定取消按钮

在模板里给每个文件项加取消按钮,只在上传中显示:

<div *ngFor="let item of droppedFilesArray" class="file-item">
  <span>{{ item.file.name }}</span>
  <div>进度:{{ item.progress }}%</div>
  <div class="status" [ngClass]="item.status">{{ item.status }}</div>
  <button *ngIf="item.status === 'uploading'" (click)="cancelSingleUpload(item)" class="cancel-btn">×</button>
</div>

二、优化方案

  1. 避免内存泄漏:组件销毁时,取消所有未完成的上传请求,防止内存泄漏:
import { OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

export class FileUploadComponent implements OnDestroy {
  private allUploadSubs = new Subscription();

  startSingleUpload(fileItem: any) {
    // ... 原有代码
    // 把单个订阅加到总订阅组里
    this.allUploadSubs.add(fileItem.uploadSub);
  }

  ngOnDestroy() {
    // 组件销毁时取消所有订阅
    this.allUploadSubs.unsubscribe();
  }
}
  1. 状态可视化优化:给不同上传状态加样式,让用户一眼看出来:
.file-item .status {
  margin: 0 8px;
}
.status.uploading { color: orange; }
.status.completed { color: green; }
.status.cancelled { color: gray; }
.status.failed { color: red; }
.cancel-btn {
  border: none;
  background: transparent;
  color: red;
  cursor: pointer;
  font-size: 18px;
}
  1. 批量操作支持:加个“取消所有上传”按钮,一键终止所有未完成的请求:
cancelAllUploads() {
  this.droppedFilesArray.forEach(item => {
    this.cancelSingleUpload(item);
  });
}
  1. 失败重试机制:给上传失败的文件加重试按钮,方便用户重新上传:
retryUpload(fileItem: any) {
  fileItem.status = 'pending';
  fileItem.progress = 0;
  this.startSingleUpload(fileItem);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:25:21