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

咨询Angular中HttpProgressEvent接口的使用方法及示例

如何在Angular中使用HttpProgressEvent接口?

我完全懂你的困扰——Angular官方文档有时候只放接口定义却不给实际示例,刚接触的时候确实摸不着头脑。不过别慌,我来一步步给你讲清楚这个接口的用法,再附上上传和下载场景的完整示例。

首先先快速回顾下这个接口的作用:HttpProgressEvent是Angular HttpClient模块中专门用于跟踪上传/下载进度的事件类型,它属于HttpEvent的子类。接口里的三个核心属性:

  • type: 固定是HttpEventType.DownloadProgress(下载进度)或者HttpEventType.UploadProgress(上传进度),用来区分是哪种进度事件
  • loaded: 已经完成传输的字节数
  • total?: 可选属性,代表总传输字节数(只有当服务器返回了Content-Length响应头时,这个值才会存在)

一、下载进度跟踪示例

假设你要从服务器下载一个大文件,同时实时显示下载进度,代码可以这么写:

首先确保你的模块已经导入了HttpClientModule:

// app.module.ts
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

然后在组件中编写下载逻辑:

// app.component.ts
import { Component } from '@angular/core';
import { HttpClient, HttpEventType, HttpProgressEvent } from '@angular/common/http';

@Component({
  selector: 'app-root',
  template: `
    <button (click)="startDownload()">开始下载</button>
    <p *ngIf="progress !== null">下载进度: {{ progress }}%</p>
  `
})
export class AppComponent {
  progress: number | null = null;

  constructor(private http: HttpClient) { }

  startDownload() {
    this.progress = null;
    // 替换成你的实际下载接口地址
    const downloadUrl = 'https://example.com/large-file.zip';

    this.http.get(downloadUrl, {
      reportProgress: true, // 必须开启,才会触发进度事件
      observe: 'events', // 监听所有HttpEvent类型,而不是只返回响应体
      responseType: 'blob' // 下载文件时设置为blob,方便后续保存
    }).subscribe({
      next: (event) => {
        // 判断当前事件是否为下载进度事件
        if (event.type === HttpEventType.DownloadProgress) {
          // 这里event就是HttpProgressEvent类型,做类型断言让TypeScript识别属性
          const progressEvent = event as HttpProgressEvent;
          // 计算进度百分比,注意处理total为undefined的情况
          if (progressEvent.total) {
            this.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
          } else {
            // 如果服务器没返回总字节数,只能显示已加载的字节数
            console.log(`已下载: ${progressEvent.loaded} 字节`);
          }
        } else if (event.type === HttpEventType.Response) {
          // 下载完成,处理返回的blob文件
          console.log('下载完成');
          const blob = event.body;
          // 创建下载链接让用户保存文件
          const url = window.URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.href = url;
          a.download = 'large-file.zip';
          a.click();
          window.URL.revokeObjectURL(url);
          this.progress = null;
        }
      },
      error: (err) => {
        console.error('下载失败:', err);
        this.progress = null;
      }
    });
  }
}

二、上传进度跟踪示例

如果是上传文件(比如表单提交带附件),同样可以用HttpProgressEvent来跟踪上传进度:

组件代码示例:

// app.component.ts
import { Component } from '@angular/core';
import { HttpClient, HttpEventType, HttpProgressEvent } from '@angular/common/http';

@Component({
  selector: 'app-root',
  template: `
    <input type="file" #fileInput (change)="onFileSelected($event)">
    <button (click)="startUpload()" [disabled]="!selectedFile">开始上传</button>
    <p *ngIf="uploadProgress !== null">上传进度: {{ uploadProgress }}%</p>
  `
})
export class AppComponent {
  selectedFile: File | null = null;
  uploadProgress: number | null = null;

  constructor(private http: HttpClient) { }

  onFileSelected(event: Event) {
    const input = event.target as HTMLInputElement;
    if (input.files?.length) {
      this.selectedFile = input.files[0];
    }
  }

  startUpload() {
    if (!this.selectedFile) return;

    this.uploadProgress = null;
    const formData = new FormData();
    formData.append('file', this.selectedFile);

    // 替换成你的实际上传接口地址
    const uploadUrl = 'https://example.com/upload';

    this.http.post(uploadUrl, formData, {
      reportProgress: true, // 开启进度报告
      observe: 'events' // 监听所有HttpEvent类型
    }).subscribe({
      next: (event) => {
        // 判断当前事件是否为上传进度事件
        if (event.type === HttpEventType.UploadProgress) {
          const progressEvent = event as HttpProgressEvent;
          if (progressEvent.total) {
            this.uploadProgress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
          } else {
            console.log(`已上传: ${progressEvent.loaded} 字节`);
          }
        } else if (event.type === HttpEventType.Response) {
          console.log('上传成功:', event.body);
          this.uploadProgress = null;
          this.selectedFile = null;
        }
      },
      error: (err) => {
        console.error('上传失败:', err);
        this.uploadProgress = null;
      }
    });
  }
}

几个关键注意点

  • 必须同时设置reportProgress: true和observe: 'events',否则HttpClient不会发出进度事件
  • total属性可能为undefined:如果服务器没有返回Content-Length响应头(比如动态生成的内容),或者上传的是流式数据,这时候只能通过loaded来了解已传输的字节数
  • 类型断言:在订阅事件时,需要把event断言为HttpProgressEvent,这样TypeScript才能正确识别loaded和total属性

内容的提问来源于stack exchange,提问作者蒋建雨

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:51:51