Tan
Tan

Reputation: 1585

handling file download from api call

In react, I am testing my file download based on John Culviner's solution mentioned in this post

axios.post('api/downloadMyFile', 
            data
           ).then((response) => {
            
             const url = window.URL.createObjectURL(new Blob([response.data])) 

             const a = document.createElement('a');

             a.href = url;
             a.download = "test.zip"  
             document.body.appendChild(a);
             a.click();
             window.URL.revokeObjectURL(url);


           
        }).catch((err) => {
            
        } 

So file test.zip is getting downloaded. but when I tried to open it after saving it I am getting Compressed Zip folder error in windows.

Also, I noticed that I don't need to specify the name of the file in the line a.download = "test.zip" because the webservice is getting the file from shared storage and it already has a name. So in this case, do I need to have the filename also in the response object? something like response.filename so that I could use it in the following line instead of naming it manually:

a.download = response.filename

Upvotes: 2

Views: 10337

Answers (2)

Mohamed Omera
Mohamed Omera

Reputation: 263

try this two lines to get the file name from the response object

var filename = response.headers.get("content-disposition");
filename = filename.match(/(?<=")(?:\\.|[^"\\])*(?=")/)[0];

Upvotes: 0

Randy Casburn
Randy Casburn

Reputation: 14175

The response.data returned from Axios is a JSON string. So creating a Blob from that JSON doesn't produce the correct object. From the Axios docs:

// responseType indicates the type of data that the server will respond with
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
// browser only: 'blob'
responseType: 'json', // default

The simple fix is to tell Axios to provide the response in the form of a Blob. Then the URL.createObjectURL() will produce a URL to a file that is in the correct format.

axios.post('api/downloadMyFile', data, { responseType: 'blob' })
.then(blob=>{
  const url = window.URL.createObjectURL(blob.data); 
  const a = document.createElement('a');
  a.href = url;
  a.download = "download.zip"  
  document.body.appendChild(a);
  a.click();
  window.URL.revokeObjectURL(url);
})

Upvotes: 2

Related Questions