How to export and download data into valid xlsx format on client side?

Viewed 1477

From the backend api I am getting a list of students data into a valid excel file which is being downloaded on hitting the endpoint /api/v1.0/students/students-xlsx/ But on the client side when I am calling this endpoint it's showing unreadable format and being downloaded as a corrupt excel file.

I followed some stackoverflow suggestions like atob, encodeURI the response data and add specific type (UTF-8) but it failed. Still I am getting the corrupt file with weird characters.

excelFileDownload() {
  this.$http.get(this.exportXLUrl)
    .then((response) => {
      response.blob().then(() => {
        const blob = new Blob([response.body], { type: response.headers.get('content-type') });
        const filename = response.headers.map['content-disposition'][0].split('filename=')[1];
        const link = document.getElementById('download-excel-file');
        link.href = window.URL.createObjectURL(blob);
        link.download = filename.split('"').join('');
        link.style.display = 'block';
        link.click();
      });
    });
},

I expect the output as same as when I am just using browsable API to call the endpoint- which is giving me the appropriate xls format file with readable characters. But on the client side I am not getting that at all. It's all broken. Any help would be appreciated to improve my code.

2 Answers

If you're willing to use XMLHttpRequest

(untested)

const xhr = new XMLHttpRequest();
xhr.open('GET', this.exportXLUrl, true);
xhr.responseType = 'blob';

xhr.addEventListener('load', () =>
{
    if(xhr.status == 200)
    {
        const url = window.URL.createObjectURL(xhr.response);

        const contentDisposition = xhr.getResponseHeader('content-disposition');
        const filename = /filename=([^;]*)/.exec(contentDisposition)[1];

        const link = document.getElementById('download-excel-file');
        link.href = window.URL.createObjectURL(blob);
        link.download = filename.split('"').join('');
        link.style.display = 'block';
        link.click();

        //Dont forget to revoke it
        window.URL.revokeObjectURL(url);
    }
    else
    {
        //error
    }
});

xhr.addEventListener('error', err =>
{
    //error
});

xhr.send();

I need to pass the Content-type in headers and responseType with the get request as below:

headers: { 'Content-Type': 'application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet' },
responseType: 'arraybuffer'

It works fine now.

Related