1

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

Tan
  • 1,433
  • 5
  • 27
  • 47

2 Answers2

1

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);
})
Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
  • Thanks Randy. Doing this worked but my response object is no longer showing in console log and doing this `console.log(blob);` showed me this. https://i.stack.imgur.com/uqABh.png . So I am unable to use the information that was getting returned with the response object. – Tan Nov 18 '20 at 19:30
  • You can use the URL you created. For example if it is an image like in your comment, the the `img.src` equal to the URL. The image will appear. – Randy Casburn Nov 18 '20 at 19:33
  • Sorry, I didn't get it. Initially, `response.data` was showing an info like `NOT AUTHORIZED` if someone is not authorized to download the file. But since we have told the axios to provide info in the form of a blob, it's showing as shown in the image above. – Tan Nov 18 '20 at 19:39
  • I mean it was showing like this before blob conversion `Object { data: "NOT_AUTHORIZED: you are not allowed to download this file", status: 200, statusText: "", headers: {…}, config: {…}, request: XMLHttpRequest }`. After blob conversion, it only shows like shown in above image – Tan Nov 18 '20 at 19:47
  • That's a different question, I have answered your original question. You should post that as a new question. Otherwise, what happens is these questions/answers continue to get extended forever. In your new question, you should be prepared to be told that your server should NOT return an HTTP status code of 200 when it should be 401 or 403. Good luck. – Randy Casburn Nov 18 '20 at 19:55
  • Yes, sure. I am going to do that. Thanks ! – Tan Nov 18 '20 at 20:11
  • I created here : https://stackoverflow.com/questions/64900864/unable-to-access-response-object-not-authorized-related-info-after-blob-conversi – Tan Nov 18 '20 at 20:28
0

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

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