0

我有在 Angular 13 / RxJs 7 中获得下载进度的工作解决方案。

首先我定义了一些枚举:

export enum RequestType {
  get = 'GET',
  post = 'POST',
  put = 'PUT',
  delete = 'DELETE',
}

export enum ActionType {
  download = 1,
  upload
}

接下来,我实现了一个共享服务来处理跟踪进度:

@Injectable({
  providedIn: 'root'
})
export class DownloadProgressService {

  percentDone = 0;
  actionType: ActionType;

  constructor(private http: HttpClient) { }

  downloadFile(uri: string, requestType: RequestType, actionType: ActionType, body: any): Observable<number> {

    this.actionType = actionType;

    const req = new HttpRequest(requestType, uri, body, {
      reportProgress: true,
      responseType: 'blob'
    });

    return this.http
      .request(req)
      .pipe(
        map(event => this.getPercentage(event)),
    );

  }

  public getPercentage(event: HttpEvent<any>): number {

    switch (event.type) {

      case HttpEventType.UploadProgress:

      // Downloading files will still trigger upload progress due to the back-and-forth, ignore this
      if (this.actionType !== ActionType.upload) {
        return 0;
      }

      // Compute and show the % done:
        if (event && event.total) {
          this.percentDone = Math.round(100 * event.loaded / event.total);
          return this.percentDone;
        } else {
          return 0;
        }

      case HttpEventType.DownloadProgress:

        if (event && event.total) {
          this.percentDone = Math.round(100 * event.loaded / event.total);
        }

        return this.percentDone;

      default:

        // Not an event we care about
        return this.percentDone;

    }
  }

}

然后,我只需订阅它并获得正确的下载进度:

this.downloadService
  .downloadFile(url, RequestType.post, ActionType.download, body)
  .subscribe(progress => this.progress = progress);

这一切都很好,我的组件库中有一个进度条,显示了真实的进度。

问题是......我如何获得结果文件?

4

1 回答 1

1

您可以返回一个包含进度百分比HTTP 响应的对象,而不是只返回进度。

return this.http.request(req).pipe(
  map(event => ({
    progress: this.getPercentage(event),
    response: event
  })),
);

现在在订阅中您可以使用该对象

this.downloadService
  .downloadFile(url, RequestType.post, ActionType.download, body)
  .subscribe({
    next: ({progress, response}) => {
      this.progress = progress;
      // use response
    },
    error: (error: any) => {
      // handle errors
    }
  });
于 2022-01-18T10:47:09.933 回答