【问题标题】:Angular / rxjs : show download progress + wait for file to be downloaded before continueingAngular / rxjs:显示下载进度+等待文件下载后再继续
【发布时间】:2020-10-08 15:34:31
【问题描述】:

在 Ionic / Angular 项目中,我有一系列 HTTP 请求需要在继续之前完成。 但我还需要在应用程序中向用户显示下载进度条。但我不知道在哪里或如何实现对 HttpEvents 的侦听,因此我可以显示加载进度。这是我目前拥有的:

downloadDocument(document: Document) {
// does a http.get to get the documents url
return this.documentsRepositoryService.getDownloadUrl(document).pipe(
  concatMap(
    //the download url is received, now download the file.
    // TODO: listen for download progress and display 0 - 100% 
    // Should wait for download to complete
    dlUrl => this.documentsRepositoryService.downloadDocument(document, dlUrl.url)
  ),
  concatMap(
    value => {
      // do something with the downloaded file I suppose

      // Update the documentstatus to "downloaded"
      // returns promise, convert to observable
      document.download(); // just sets the document's state as downloaded
      return of(this.documentsRepositoryService.update(document));
    }
  ),
  concatMap(
    value => {
      // now do a httprequest to confirm to the api, the file is downloaded
      return this.documentsRepositoryService.confirmDownloadToAPI(document);
    }
  ),
  concatMap(
    value => {
      // sequence is done.
      this.setBadge();
      return value;
    }
  )

)
}

该方法返回一个我订阅的可观察对象:

onDownload(document) {

this.downloadManager.downloadDocument(document).subscribe(
  value => {
    // currently runs 
    console.log("downloaded");
  }
);

}

目前“下载的”console.log 显示 2 次,我怀疑下载何时开始和何时结束?所以这不是正确的做法。

我在此主题上找到的几个示例在订阅中监听文档下载进度,但我不知道如何在管道中或至少按顺序执行此操作。 或者这是实现这一目标的更好方法?

谢谢

【问题讨论】:

  • 这里已经隐藏了足够多的实现,但看起来您已经创建了一系列流,每个流都发出一个。所以你真的应该让你的订阅 lambda 被执行一次。花费一些调试时间来确定哪个调用产生了两次排放是值得的。
  • 如果您使用第三方 API 上传和/或下载数据块,那么如何将进度传递给您取决于 API。 HTTP 作为协议没有内置下载/上传进度。除非我遗漏了什么,否则这个问题在它所处的状态下是无法回答的。

标签: angular http rxjs


【解决方案1】:

编辑:仍然不是“解决方案”,因为没有收到最终对象,只有进度消息。

编辑 2:找到它,下面的代码将结果“更改”为 map() 函数中的字符串。

我在官方文档中找到了答案。 运行两次的错误是因为我没有在downloadFile方法中使用“last()”。它基本上将所有事件发送通过。 现在报告进度。 最后要做的是更改下面的代码,这样它就不会发送字符串而是发送事件本身。

downloadFile(filesrc) {
    const req = new HttpRequest('GET', filesrc, null, {
      reportProgress: true,
      responseType: 'blob'
      
    });
   
    return this.http.request(req).pipe(
      map(event => this.getEventMessage(event)),
      tap(message => this.showProgress(message)),
      last(), // return last (completed) message to caller
    );

  }
 
  showProgress(message ){
    console.log(message);
  }

  getEventMessage(event: HttpEvent<any>) {
    console.log('event is', event);
    switch (event.type) {
      case HttpEventType.Sent:
        
        return `sending request`;

      case HttpEventType.UploadProgress:
        // Compute and show the % done:
        const percentDone = Math.round(100 * event.loaded / event.total);
       
        return `File is ${percentDone} uploaded.`;

      case HttpEventType.Response:
        
        return `File was completely uploaded!`;

      case HttpEventType.DownloadProgress:
        const percentDoneDL = Math.round(100 * event.loaded / event.total);
        
        return `File is ${percentDoneDL} downloaded`;

      case HttpEventType.ResponseHeader:
       
        return `Response headers are received`

      default:
        
        return `File surprising upload event: ${event.type}.`;
    }
  }

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多