文件上传进度检查文件是否在Angular 7中作为FormData发送?

net*_*djw 11 file-upload multipartform-data form-data angular angular7

我上传文件FORMDATA在角7使用此代码HttpClienthttp:

sendImageFile(subUri: string, id: number, fileToUpload: File): Observable<any> {
  const formData: FormData = new FormData();
  formData.append('file', fileToUpload, fileToUpload.name);
  formData.append('photoalbum_id', id.toString() );
  // ... some other .append()

  const customHeaders = new HttpHeaders({
    'Authorization': 'Bearer' + localStorage.getItem('token'),
    'Accepted-Encoding': 'application/json'
  });

  const customOptions = {
    headers: customHeaders,
    reportProgress: true
  };

  return this.http.post(this.url, formData, customOptions)
    .pipe(
      map( (event: HttpEvent<any>) => this.getEventMessage(event, fileToUpload)),
      tap(message => this.showProgress(message)),
      // last(),
      catchError(this.handleError));
}

private showProgress(message: any) {
  // ...
}

private getEventMessage(event: HttpEvent<any>, file: File) {
  // ...
}
Run Code Online (Sandbox Code Playgroud)

主要问题是这里没有检查上传,因为文件是上传的部分,FormData所以在上传完成之前我没有得到任何反馈.

我对这个进度检查有点困惑.我必须将文件上传为FormData.在这种情况下,如何检查上传进度?

Dea*_*ean 8

答案在于HttpClient实施.通过该HttpClient.post方法创建的所有请求都将observe属性默认为body.有关详细信息,请参阅此HttpClient.post方法.这意味着:即使您成功设置reportProgresstrue,生成的observable也会观察请求体而不是HttpEvents.从文档(强调我的):

observe值根据消费者对观察感兴趣的内容确定request()的返回类型.事件值将返回Observable<HttpEvent>表示原始HttpEvent流的值,默认情况下包括进度事件.响应值将返回Observable<HttpResponse<T>>HttpResponse的T参数取决于responseType和任何可选提供的类型参数的位置.body的值将返回Observable<T>具有相同T体类型的值.

该文档还指出,如果您将HttpRequest实例传递给request,它将HttpEvent默认返回流的可观察对象:

可以通过两种方式之一调用此方法.可以将HttpRequest实例作为唯一参数直接传递,也可以将方法作为第一个参数传递,将字符串URL作为第二个参数传递,将选项哈希作为第三个参数传递.

如果直接传递HttpRequest对象,将返回原始HttpEvent流的Observable.

因此,观察HttpEvent流的最简单方法是HttpRequest直接传递对象,如下所示:

sendImageFile(subUri: string, id: number, fileToUpload: File): Observable<any> {
  const formData: FormData = new FormData();
  formData.append('file', fileToUpload, fileToUpload.name);
  formData.append('photoalbum_id', id.toString());
  // ... some other .append()

  const customHeaders = new HttpHeaders({
    'Authorization': 'Bearer' + localStorage.getItem('token'),
    'Accepted-Encoding': 'application/json'
  });

  const customOptions = {
    headers: customHeaders,
    reportProgress: true,
  };

  const req = new HttpRequest('POST', this.url, formData, customOptions);

  // Call HttpClient.request with an HttpRequest as only param to get an observable of HttpEvents
  return this.http.request(req)
    .pipe(
      map((event: HttpEvent<any>) => this.getEventMessage(event)),
      catchError(this.handleError));
}

private getEventMessage(event: HttpEvent<any>) {
  // We are now getting events and can do whatever we want with them!
  console.log(event);
}
Run Code Online (Sandbox Code Playgroud)

我在本地存储库上测试了这个重构的代码,它运行得很好.