Проверка прогресса загрузки файла, если файл отправлен как FormData в Angular 7? - PullRequest
0 голосов
/ 06 января 2019

Я загружаю файл как FormData в Angular 7 с этим кодом, используя HttpClient как http:

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) {
  // ...
}

Основная проблема здесь не в том, чтобы проверить загрузку, потому что файл загружен как часть FormData, поэтому я не получаю никаких отзывов, пока загрузка не закончится.

Я немного растерялся из-за этой проверки прогресса. Я должен загрузить файл как FormData. Как я могу проверить ход загрузки в этом случае?

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Ответ лежит в реализации HttpClient. Все запросы, созданные с помощью метода HttpClient.post, по умолчанию для свойства observe равны body. Подробнее см. этот метод HttpClient.post . Это означает следующее: даже если вы успешно установили reportProgress в true, полученная в результате наблюдаемая будет наблюдать тело запроса вместо HttpEvents. С Документы (выделено мое):

Значение наблюдения определяет тип возврата request (), основываясь на том, что потребитель заинтересован в наблюдении. Значение события вернет Observable<HttpEvent>, представляющий необработанный поток HttpEvent , включая события прогресса по умолчанию. Значение response будет возвращать Observable<HttpResponse<T>>, где параметр T HttpResponse зависит от responseType и любого необязательного параметра типа. Значение body вернет Observable<T> с тем же типом тела T .

В документации также отмечается, что если вы передадите экземпляр HttpRequest в request, он вернет наблюдаемый поток HttpEvent по умолчанию:

Этот метод может быть вызван одним из двух способов. Либо экземпляр HttpRequest можно передать непосредственно в качестве единственного параметра, либо метод можно передать в качестве первого параметра, строковый URL-адрес в качестве второго и хэш параметров в качестве третьего.

Если объект HttpRequest передается напрямую, возвращается Observable необработанного потока HttpEvent.

Итак, самый простой способ наблюдать поток 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);
}

Я протестировал этот переработанный код в локальном репозитории, и он работал просто отлично.

0 голосов
/ 06 января 2019

РЕДАКТИРОВАНИЕ:
Из-за того, что Angular растет, как я предложил в моем предыдущем ответе, пакет npm не будет соответствовать вашим потребностям. Итак, вот что вы можете сделать:

private getEventMessage(event: HttpEvent<any>, file: File) {
  switch (event.type) {
    case HttpEventType.Sent:
      return `Uploading file "${file.name}" of size ${file.size}.`;

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

    case HttpEventType.Response:
      return `File "${file.name}" was completely uploaded!`;

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

и затем вы можете изменить функцию showProgress () в соответствии с возвращенными значениями getEventMessage (). Это помогает?

...