Angular 5 download excel file with post request

user5497854 picture user5497854 · Mar 22, 2018 · Viewed 12.8k times · Source

I am facing an issue where I have downloaded an Excel file with Angular 1 but if I am implementing the same code in Angular 5 it is showing the error that your file is corrupted. My response is in ArrayBuffer and I am unable to read the file.

Below is my code:

Service:

 DownloadData(model:requiredParams):Observable<any>{
  const headers = new Headers();
  const requestOptions = new RequestOptions({ headers: headers });
  requestOptions.headers.append('Content-Type', 'application/json');

   const body = JSON.stringify(model);
  return this.http.post(url, body, requestOptions)
  .map((res:any) => res)
 .catch((e: any) => Observable.throw(this.errorHandler(e)));
 }

Component:

exportToExcel() {
    this.loadingOverlayFlag = true;
   this.podashboardService.DownloadData(this.data).subscribe(result=>{
    console.log(result);
    this.downloadFile(result._body,'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'export.xlsx');
  })
  }

 downloadFile(blob: any, type: string, filename: string) {

 var binaryData = [];
   binaryData.push(blob);

     const url = window.URL.createObjectURL(new Blob(binaryData, {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})); // <-- work with blob directly

     // create hidden dom element (so it works in all browsers)
     const a = document.createElement('a');
     a.setAttribute('style', 'display:none;');
     document.body.appendChild(a);

     // create file, attach to hidden element and open hidden element
     a.href = url;
     a.download = filename;
     a.click();

   }

I am able to download the file, but unable to read its content. The error is:

Microsoft Excel
Excel cannot open the file '███████ DASHBOARD (5).xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file. OK

Answer

Ovi picture Ovi · Mar 23, 2018

I struggle with this one all day. Replace angular HttpClient and use XMLHttpRequest as follows:

var oReq = new XMLHttpRequest();
  oReq.open("POST", url, true);
  oReq.setRequestHeader("content-type", "application/json");
  oReq.responseType = "arraybuffer";

  oReq.onload = function (oEvent) {
    var arrayBuffer = oReq.response;
    if (arrayBuffer) {
      var byteArray = new Uint8Array(arrayBuffer);
      console.log(byteArray, byteArray.length);
      this.downloadFile(byteArray, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'export.xlsx');
    }
  };

  oReq.send(body);

Then modified the creation of the Blob in your downloadFile function:

const url = window.URL.createObjectURL(new Blob([binaryData]));

In your case the service will look something like this:

DownloadData(model:requiredParams):Observable<any>{
  return new Observable(obs => {
    var oReq = new XMLHttpRequest();
    oReq.open("POST", url, true);
    oReq.setRequestHeader("content-type", "application/json");
    oReq.responseType = "arraybuffer";

    oReq.onload = function (oEvent) {
      var arrayBuffer = oReq.response;
      var byteArray = new Uint8Array(arrayBuffer);
      obs.next(byteArray);
    };

    const body = JSON.stringify(model);
    oReq.send(body);
  });
}

Then the component:

exportToExcel() {
  this.loadingOverlayFlag = true;
  this.podashboardService.DownloadData(this.data).subscribe(result=>{
    // console.log(result);
    this.downloadFile(result,'application/vnd.openxmlformats-
    officedocument.spreadsheetml.sheet', 'export.xlsx');
  })
}

downloadFile(blob: any, type: string, filename: string) {

  var binaryData = [];
  binaryData.push(blob);

  const url = window.URL.createObjectURL(new Blob(binaryData, { type: filetype })); // <-- work with blob directly

   // create hidden dom element (so it works in all browsers)
   const a = document.createElement('a');
   a.setAttribute('style', 'display:none;');
   document.body.appendChild(a);

   // create file, attach to hidden element and open hidden element
   a.href = url;
   a.download = filename;
   a.click();
}