12

I want to download xlsx file from the client on angular 2 using rest api.

I'm getting a byte array as a response from my GET request and I'm sending it to download function with subscribe:

let options = new RequestOptions({ search: params });
this.http.get(this.restUrl, options)
          .subscribe(this.download); 

download function using blob:

download(res: Response) {
let data = new Blob([res.arrayBuffer()], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' });
FileSaver.saveAs(data, this.fileName);};

my problem is that my file is corrupted all the time. I tried a lot of versions of this but nothing works.

** also tried it with this solution and it doesn't works (the xlsx file is still corrupted) - Angular 2 downloading a file: corrupt result , the difference is that my data is an array Buffer and not string or json, and there is a difference between PDF and xlsx.

10x!

reut
  • 241
  • 1
  • 3
  • 11
  • Possible duplicate of [Angular 2 downloading a file](http://stackoverflow.com/questions/38793859/angular-2-downloading-a-file) – jlew Dec 06 '16 at 15:06
  • This is what worked for me : https://stackoverflow.com/questions/41771041/angular2-download-excel-file-from-web-api-file-is-corrupt/44680057#44680057 – Deepak Jun 21 '17 at 15:20

6 Answers6

13

I was having the same problem as yours - fixed it by adding responseType: ResponseContentType.Blob to my Get options. Check the code below:

public getReport(filters: ReportOptions) {
    return this.http.get(this.url, {
            headers: this.headers,
            params: filters,
            responseType: ResponseContentType.Blob
        })
        .toPromise()
        .then(response => this.saveAsBlob(response))
        .catch(error => this.handleError(error));
}

The saveAsBlob() is just a wrapper for the FileSaver.SaveAs():

private saveAsBlob(data: any) {
    const blob = new Blob([data._body],
        { type: 'application/vnd.ms-excel' });
    const file = new File([blob], 'report.xlsx',
        { type: 'application/vnd.ms-excel' });

    FileSaver.saveAs(file);
}
vergatti
  • 166
  • 1
  • 6
  • 2
    Works! The key piece I was missing with my issue was setting `responseType: 'blob'` (using axios), did not even need the `const file = ...`. Just made a `blob` then did `FileSaver.saveAs(blob, 'report.xlsx')` – Cumulo Nimbus Sep 27 '18 at 16:23
  • 2
    Hi This also works for me but i have change ```responseType: 'blob'```, this works for me of both files ```.csv``` & ```.xlsx``` type files. Please find my code.... ```return this.http.get(url, { headers: headers, responseType: 'blob', observe: 'response' });``` – Sanjay Tiwari Jun 14 '19 at 12:41
8

After nothing works. I changed my server to return the same byte array with the addition of:

    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setHeader("Content-Disposition", "attachment; filename=deployment-definitions.xlsx");

At my client I deleted the download function and instead of the GET part i did:

window.open(this.restUrl, "_blank");

This is the only way I found it possible to save an xlsx file that is not corrupted.

If you have a answer about how to do it with blob please tell me :)

reut
  • 241
  • 1
  • 3
  • 11
  • This is what I ended up having to do. I tried to use the url creation from a blob and the browser could not figure out how to open the file. I tried all the methods in this post plus many others. http://stackoverflow.com/questions/35138424/how-do-i-download-a-file-with-angular2 The solution you provided worked perfectly. Thanks!!! – hewstone May 19 '17 at 12:56
  • Hats off to you,You save my day @reut – Ameya Salagre Aug 23 '18 at 21:37
  • Using above approach how to pass the data from client to server to dowload specific data. Can you please help – Soumya Gangamwar Jul 19 '20 at 18:17
3

you can use the below code :

var file = new Blob([data], { 
    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 
});
saveAs(file,"nameFile"+".xlsx");
deferred.resolve(data);
Peter Szekeli
  • 2,712
  • 3
  • 30
  • 44
  • yes, It worked, but I needed to add this also, to work `let headers = new HttpHeaders();` `headers = headers.append('Accept', '*/*; charset=utf-8');` `return this.http.get('/api/v1/file/stores/download' , {` `headers: headers,` `observe: 'response',` `params: paramsRef,` `responseType: 'blob'` `});` – Parth Developer Jul 08 '21 at 08:53
0

The following solution worked for me in Google Chrome Version 58.0.3029.110 (64-bit).

It's an article explaining how to download a pdf using a Blob: https://brmorris.blogspot.ie/2017/02/download-pdf-in-angular-2.html

It's the same principle for a xlsx file. Just follow the steps from the article and change two things:

  • Header, instead of {'Accept': 'application/pdf'}, use {'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'};
  • Blob, use the same type for the creation of your Blob, new Blob([fileBlob], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}).

The article is using File Saver but I didn't. I left a comment, in the article, with a basic explanation of what I used instead of File Saver.

0

Here is the solution that supports IE and chrome/safari browsers. Here 'response' object is response received from service. I have this working for archive. You can change the type as per the response received from service.

    let blob = new Blob([response], {type: 'application/zip'});
    let fileUrl = window.URL.createObjectURL(blob);
    if (window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(blob, fileUrl.split(':')[1] + '.zip');
    } else {
        this.reportDownloadName = fileUrl;
        window.open(fileUrl);
    }
Dilip Nannaware
  • 1,410
  • 1
  • 16
  • 24
0

For me problem was, that my responseType was "text". Instead I needed to use "blob"; It works for me on Angular 7.2.15.

Andris
  • 3,895
  • 2
  • 24
  • 27