tommueller
tommueller

Reputation: 2496

HttpRequest and reportProgress not working or messing up my requests

I am implementing a file upload service with Angular 5 and I want to give the user some feedback on the upload progress. I found several pages suggesting to use the reportProgress parameter that comes with Angulars HttpClient, but I cannot get it working.

I use a wrapper class for all my http-requests, which then does some logic and finally all requests end up in the same method that's being called:

public request(request: HttpRequest<any>, options?: any): Observable<any> {
  return this.httpClient.request(request.method, request.url, {
    body: request.body,
    headers: request.headers,
    responseType: request.responseType,
    ...options
  });
}

I then pass a upload (post) call to it, with { reportProgress: true } as options. This did not work at all, nothing on the request changed. So I suspected, that I actually need to use the reportProgress-parameter in the HttpRequest constructor to make it work and changed my code accordingly:

public request(request: HttpRequest<any>, options?: any): Observable<any> {
  return this.httpClient.request(
    new HttpRequest(request.method, request.url, request.body, {
      headers: request.headers,
      responseType: request.responseType,
      ...options
    })
  );
}

This leads to the even more weird behavior, that now no matter what my options look like, I always only receive {type: 0} as response from the request.

What am I overseeing? I use Angular 5.1.1 and I am really a bit puzzled here right now.

So to give an explicit example, right now I receive the same response for those two HttpRequests:

{  
  "url":"http://127.0.0.1:8888/test",
  "body":{  
   "data":"testdata"
  },
  "reportProgress":false,
  "withCredentials":false,
  "responseType":"json",
  "method":"POST",
  "headers":{ some-headers ... }
}

and this request:

{  
  "url":"http://127.0.0.1:8888/api/pages",
  "body":{  
    "pageUrl":"http://localhost:1234/"
  },
  "reportProgress":true,
  "withCredentials":false,
  "responseType":"json",
  "method":"POST",
  "headers":{ some-headers ... }
}

Upvotes: 6

Views: 18439

Answers (7)

Hussein AbdElaziz
Hussein AbdElaziz

Reputation: 500

if You Are using service worker you have to send ngsw-bypass header.

example:-

file: File;

uploadProgress: number;

constructor(private http: HttpClient) { }

uploadData(): void {

    const formData = new FormData();
    formData.append('file', this.file);


    const headers = new HttpHeaders({ 'ngsw-bypass': '' });

    this.http.post(`upload url`, formData, {
      reportProgress: true,
      observe: 'events',
      headers
    }).subscribe(event => {

            if (event.type === HttpEventType.UploadProgress) {
                this.uploadProgress = Math.round(100 * event.loaded / event.total);
            }
            else if (event.type === HttpEventType.Response) {
                console.log(event.body);
            }

        });
  }

Upvotes: 2

Rijo
Rijo

Reputation: 3043

Upload the formdata along with header details

This snipet will help ou to upload formdata and while subscribe you can implement the progress bar as well

uploadMyImage(formData: any) {
    const httpOptions = new HttpHeaders({
      'Content-Type': 'multipart/form-data', 'boundary': 'something'
      });
    return this.http.post('http://localhost:4000/api/upload', formData, { reportProgress: true, observe: 'events', headers: httpOptions });
  }

Upvotes: 0

Shantam Mittal
Shantam Mittal

Reputation: 383

along with {reportProgress: true} you would need to send {observe: 'events'}

this.httpClient.post(environment.uploadDocument, file, { reportProgress: true, observe: 'events' })
.subcribe(data =>{
if (data['type'] === HttpEventType.UploadProgress) {
   console.log('loaded ', data['loaded'], '   total  -', data['total']);
   }
})

Upvotes: 11

C.M.
C.M.

Reputation: 1561

After reading https://stackoverflow.com/a/54899930/1429439 I added the observe: 'events' parameter and started receiving the HttpEvents in my subscription.

Upvotes: 3

mpunit30
mpunit30

Reputation: 391

return this.http.request('POST', api_enpoint , { body: body, headers: headers, reportProgress: true, withCredentials: true }).map(httpResponse => {
   console.log(httpResponse);
});

Instead of passing the httpRequest object, you need to pass the request in this fashion (works for both http as well for https)

Upvotes: 1

tommueller
tommueller

Reputation: 2496

I solved the issues. There were actually two things that were involved in the behavior described in the question.

First of all ... rtfm! https://angular.io/api/common/http/HttpClient

This method [HttpClient.request()] can be called in one of two ways. Either an HttpRequest instance can be passed directly as the only parameter, or a method can be passed as the first parameter, a string URL as the second, and an options hash as the third.

If a HttpRequest object is passed directly, an Observable of the raw HttpEvent stream will be returned.

This explains why my two request (both passed as HttpRequest returned {type: 0} from now on, regardless of the reportProgress-paramter being true or false.

Only receiving the SENT-event ({type: 0}) on the other hand was a missconfiguration of the backend itself.

Upvotes: 4

Sam B
Sam B

Reputation: 115

This method may help

public progress: number = 0;
public message: string = "";

constructor(private http: HttpClient) {}

onSubmit() {
    // replace with your request data
    const formModel = this.userForm.value;
    let formData = new FormData();

    formData.append("upload", formModel.upload);

    const uploadReq = new HttpRequest('POST', 'api/Upload', formData, {
        reportProgress: true,
    });

    this.http.request(uploadReq).subscribe((event) => {
        if (event.type === HttpEventType.UploadProgress) {
            this.progress = Math.round(100 * event.loaded / event.total);
        }
        else if (event.type === HttpEventType.Response) {
            this.message = event.body.toString();
        }
    });
}

Upvotes: 6

Related Questions