3

I have an Axios request to download the .xls file. Problem is that the object returned as a response from backend doesn't always has to be a real file. If I return json object instead of file data. How I would read this json then?

Here is the function:

downloadReport() {
  let postConfig = {
    headers: {
      'X-Requested-With': 'XMLHttpRequest'
    },
    responseType: 'blob',
  } as AxiosRequestConfig

  axios
  .post(this.urls.exportDiscountReport, this.discount.id, postConfig)
  .then((response) => {
    let blob = new Blob([response.data], { type: 'application/vnd.ms-excel' });
    let url = window['URL'].createObjectURL(blob);
    let a = document.createElement('a');
    a.href = url;
    a.download = this.discount.id + ' discount draft.xlsx';
    a.click();
    window['URL'].revokeObjectURL(url);
  })
  .catch(error => {
  })
}

I would like to read the response and if it contains some data in it - don't create the blob and initiate the download, instead, just show some message or whatever. If I remove the responseType: 'blob' then the .xls file downloads as unreadable and not valid file.

So the problem is that every returned response becomes blob type and I don't see my returned data in it. Any ideas?

2 Answers 2

7

Have you tried checking the responseBlob.type property? It gives the MIME type of the returned data.

So for example you could have something like this:

const jsonMimeType = 'application/json';
const dataType = responseBlob.type;

// The instanceof Blob check here is redundant, however it's worth making sure
const isBlob = responseBlob instanceof Blob && dataType !== jsonMimeType;

if (isBlob) {

  // do your blob download handling

} else {
  responseBlob.text().then(text => {
    const res = JSON.parse(text);
    // do your JSON handling
  });
}

This I find is much simpler and works for me, however it depends on your backend setup. The BLOB response is still a text response, but it's handled slightly differently.

Sign up to request clarification or add additional context in comments.

Comments

6

I solved this by reading the blob response and checking if it has JSON parameter status. But this looks like an overengineering to me. Is there a better solution?

let postConfig = {
  headers: {
    'X-Requested-With': 'XMLHttpRequest'
  },
  responseType: 'blob',
} as AxiosRequestConfig

axios
  .post(this.urls.exportDiscountReport, this.discount.id, postConfig)
  .then((responseBlob) => {
    const self = this;
    let reader = new FileReader();

    reader.onload = function() {
      let response = { status: true, message: '' };

      try {
        response = JSON.parse(<string>reader.result);
      } catch (e) {}

      if (response.status) {
        let blob = new Blob([responseBlob.data], { type: 'application/vnd.ms-excel' });
        let url = window['URL'].createObjectURL(blob);
        let a = document.createElement('a');
        a.href = url;
        a.download = self.discount.id + ' discount draft.xlsx';
        a.click();
        window['URL'].revokeObjectURL(url);
      } else {
        alert(response.message)
      }
    }
    reader.readAsText(responseBlob.data);
  })
  .catch(error => {
  })

I also found the same solution here: https://github.com/axios/axios/issues/815#issuecomment-340972365

Still looks way too hacky.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.