html
<h4>⏳下载中... {{ downloadPercentage>0?downloadPercentage+' %':'' }}</h4>
<small *ngIf="downloadPercentage<100">{{ currentSpeed }}</small>
<ion-progress-bar [color]="downloadPercentage>=100?'success':'primary'"
[value]="downloadPercentage/100"></ion-progress-bar>
<ion-button size="small" fill="clear" (click)="onCancelClick();">取消</ion-button>
ts
import { Component, OnInit } from '@angular/core';
import { NavParams, PopoverController } from '@ionic/angular';
import { HttpClient, HttpEvent, HttpEventType, HttpRequest, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { catchError, map, Observable, of, Subscribable, Subscriber, Subscription } from 'rxjs';
import { InteractionService } from '../InteractionService';
import { Directory, Filesystem } from '@capacitor/filesystem';
@Component( {
selector: 'app-download-pop',
templateUrl: './download-pop.component.html',
styleUrls: ['./download-pop.component.scss'],
} )
export class DownloadPopComponent implements OnInit {
public downloadPercentage: number = 0;
public currentSpeed: string = '';
private downloadUrl: string = '';
private downloadSub?: Subscription;
public constructor(
private popoverCtrl: PopoverController,
private navParams: NavParams,
private http: HttpClient,
private interactionService: InteractionService,
) {
this.downloadUrl = this.navParams.data['downloadUrl'] as string;
if ( !this.downloadUrl ) { return; }
}
public ngOnInit(): void {
this.download();
}
public async download() {
const req = new HttpRequest( 'get', 'VideoFile/DownloadFile?path=' + this.downloadUrl
, { responseType: 'blob', reportProgress: true } );
this.downloadSub = this.http.request<Blob>( req ).pipe(
map( m => this.getEventMessage( m ) ),
catchError( () => this.handleError() ),
).subscribe();
}
private handleError(): Observable<string> {
( error: HttpErrorResponse ) => {
const message = ( error.error instanceof Error ) ?
error.error.message :
`server returned code ${error.status} with body "${error.error}"`;
this.interactionService.toast( message ).then().catch();
return of( message )
}
return of( '' );
}
private async WriteFile( blob: Blob, headers: HttpHeaders ): Promise<void> {
let fileName: string = decodeURIComponent( headers.get( 'Content-Disposition' )?.split( "filename*=UTF-8''" )[1] ?? '' );
let base64Data = ( await this.convertBlobToBase64( blob ) ) as string;
await Filesystem.writeFile( {
path: fileName,
data: base64Data,
directory: Directory.Documents,
} );
await this.onCancelClick();
}
public convertBlobToBase64 = ( blob: Blob ) =>
new Promise( ( resolve, reject ) => {
const reader = new FileReader();
reader.onerror = reject;
reader.onload = () => {
resolve( reader.result );
};
reader.readAsDataURL( blob );
} );
private getEventMessage( event: HttpEvent<any> ): Observable<boolean> {
switch ( event.type ) {
case HttpEventType.Sent:
console.log( '开始下载' );
return of( false );
case HttpEventType.DownloadProgress:
let percentDone: number = Math.round( 100 * event.loaded / event!.total! );
this.downloadPercentage = percentDone;
console.log( '计算进度' );
return of( false );
case HttpEventType.Response:
this.WriteFile( event.body, event.headers ).then().catch();
console.log( '下载完成' );
return of( true );
default:
console.log( '.....' );
return of( false );
}
}
public async onCancelClick(): Promise<void> {
this.downloadSub!.unsubscribe();
await this.close();
}
private async close(): Promise<void> {
let top: HTMLIonPopoverElement | undefined = await this.popoverCtrl.getTop();
if ( top ) {
await top.dismiss();
}
}
}