Download .xls file using Angular: Unexpected token P in JSON at position 0 at JSON.parse (<anonymous>)

For Angular 8+

return this.http.get(endpoint, { responseType: 'blob'});

return this.http.post(endpoint, postParams, { responseType: 'blob'});

It is subtle but if you look at the docs you will notice http.post and http.get does not take a generic return type of <T> when we set responseType: 'blob'. So we don't need the <Blob> part in http.get<Blob> anymore. Which makes sense when you think about it since we are telling HttpClient the response is of type blob with responseType: 'blob'.

https://angular.io/api/common/http/HttpClient#post

Angular 8 HttpClient blob doc

If you need something besides 'blob' here are the other options available for responseType.

responseType: 'arraybuffer' | 'blob' | 'json' | 'text'

https://angular.io/api/common/http/HttpRequest#responseType


You can set the responseType in the get-request directly like this:

return this.http.get(endpoint, { responseType: 'application/octet-stream'});

Edit June 2020 - in Angular 9 there are four response types supported: 'arraybuffer'|'blob'|'json'|'text'. So 'application/octet-stream' would need to be replaced with 'blob' as @ryan-e pointed out in his answer.

More information is here in the docs.

Your content-type header is only used for the request-header, it does not influence the response.


I resoloved the problem in Angular 9.1.4 by using responseType blob and setting type in BlobPropertyBag later, e.g. for Excel files:

 return this.httpClient.get(url, {
  responseType: 'blob',
  params: queryParams
})
  .pipe(
    map((res: any) => {
      const blob = new Blob([res], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
      return blob;
    })
  );