Jean-Luc Aubert
Jean-Luc Aubert

Reputation: 620

HttpErrorResponse while downloading a file from a server

I spent lot a lot of time to find a solution using 'file-saver' angular module to handle a file download from my apache server.

In the front-end, the method used to download is :

 public download(document: any): void {
    const headers = new HttpHeaders();
    headers.append('Accept', 'application/octet-stream, */*');
    this.api.download(document.id, headers).subscribe((response) => {
      this._save(response);
    });
  }

The 'api' do the following :

  public download(id: number, headers: HttpHeaders): Observable<any> {
    return this.http.get<any>(
      Constants._ICE_API_ROOT + 'Download/' + id,
      { headers }
    );
 }

When i run the Angular App and check the console, get HttpErrorResponse :

HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://crmapi.wrk/Download/2", ok: false, …}

SyntaxError: Unexpected token P in JSON at position 0 at JSON.parse (<anonymous>) 

And it seems to be correct as the content returned by the server is the content of the file i want to download...

At the backend side, the PHP code is simple :

$path = $document->folder . $document->name;
if (array_key_exists("HTTP_ACCESS_CONTROL_REQUEST_HEADERS", $_SERVER)) {
    header("Access-Control-Allow-Headers: " . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] . "," . $document->type);
} else {
    header("Access-Control-Allow-Headers: " . $document->type);
}
header("Content-Disposition: attachment; filename=" . $document->name);
header("Content-Type: " . $document->type);
header("Content-Transfer-Encoding: Binary");
header("Content-Length:". $document->size);

readfile($path);
exit();

So my questions :

Thx

Upvotes: 0

Views: 1619

Answers (2)

Jean-Luc Aubert
Jean-Luc Aubert

Reputation: 620

Finally, and according to @AshishRanjan solutions, i update my code this way :

component code :

public download(document: any): void {
    const headers = new HttpHeaders();
    headers.append('Accept', document.type);
    this.api.download(document.id, headers).subscribe((response) => {
      this._save(response, document);
    });
  }


  private _save(rawDocument: Blob, document: any): void {
    saveAs(rawDocument, document.name);
  }

API :

public download(id: number, headers: HttpHeaders): Observable<any> {
    return this.http.get(
      Constants._ICE_API_ROOT + 'Download/' + id,
      { headers: headers, responseType: 'blob' as 'blob' }
    );
  }

Upvotes: 0

Ashish Ranjan
Ashish Ranjan

Reputation: 12960

Please use {responseType: ResponseContentType.Blob} in RequestOptions while sending the request. Import ResponseContentType from @angular/http.

And hopefully through this._save() you are using filesaver's saveAs(). Although it shouldn't be a problem but try using with this._save(response.blob())


For HttpClient, I don't think there is any ResponseContentType, I believe what will work for you will be: {responseType: 'blob'} or {responseType: 'text'} try either.

You don't have to set this as a header in the request, responseType is part of RequestOptions as pointed out in a comment below.. Have a look at this: https://angular.io/api/common/http/HttpClient#get

So, basically your request will look something like:

this.http.get<any>(url, { headers: yourHeaders, responseType: 'blob'});

Upvotes: 1

Related Questions