Angular / RxJs:下载进度
Angular / RxJs: Download Progress
我有在 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);
这一切都很好,我的组件库有一个进度条,显示了实际进度。
问题是……如何获得结果文件?
您可以 return 包含进度百分比 和 HTTP 响应的对象,而不是仅 return 进度。
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
}
});
我有在 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);
这一切都很好,我的组件库有一个进度条,显示了实际进度。
问题是……如何获得结果文件?
您可以 return 包含进度百分比 和 HTTP 响应的对象,而不是仅 return 进度。
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
}
});