ionic 文件下载进度显示 &取消下载,Filesystem保存blob到系统

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();
    }
  }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值