Download file in react client from flask remote server

Question:

I have a post fetch request coming from my React client to my remote Flask server like so:

fetch(FETCH_URL, {
  method: 'POST',
  body: data,
  headers: {
    'Content-Type': 'application/json'
  }
}).then((response) => {
    var a = response.body.getReader();
    a.read().then(({ done, value }) => {
        console.log(new TextDecoder("utf-8").decode(value));
      }
    );
});

response.body comes in the form of a ReadableStream object so I was able to extract a Uint8array which I then decoded to be the contents of the txt file I sent back from my flask server as shown in the code above.

At this point I’m lost, what I’m trying to do is send a request to my remote server with a filename (in the requests’ data), and download that file on my computer.

As shown above, I tried a fetch request to my remote server, then in flask, my server finds and opens the file which is stored on the server itself, and sends back the file.

filename = request.get_json()['filename']
f = open(filename)
return f

The problem now is that from what I’ve read, I can’t create a file on my computer just with react. Even so, I don’t know if this would work with all types of files or just txt files. Does anyone have any guidance to get to my end goal of downloading a file from a remote flask server.

Asked By: bwad

||

Answers:

If your requirement is to create a file with data you received from the response. The below solution should work.

  1. Create the blob object with the text you received
  2. Create Blob Object URL for that blob
  3. Trigger downloading the object using that URL

Since this is pure Javascript solution, it’s independent of React or any library you use.

Solution:

fetch(FETCH_URL, {
  method: 'POST',
  body: data,
  headers: {
    'Content-Type': 'application/json'
  }
}).then((response) => {
    var a = response.body.getReader();
    a.read().then(({ done, value }) => {
        // console.log(new TextDecoder("utf-8").decode(value));
        saveAsFile(new TextDecoder("utf-8").decode(value), 'filename');
      }
    );
});


function saveAsFile(text, filename) {
  // Step 1: Create the blob object with the text you received
  const type = 'application/text'; // modify or get it from response
  const blob = new BlobBuilder([text], {type});

  // Step 2: Create Blob Object URL for that blob
  const url = URL.createObjectURL(blob);

  // Step 3: Trigger downloading the object using that URL
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click(); // triggering it manually
}
Answered By: Kamalakannan J

Alternatively, you can use <Button href="${YOUR_FILE_URL}"/> to download the file sent by flask.

Answered By: pleiadesian

To add to Kamalakannan’s post, if you are never going to use that element again make sure to removeChild() and revokeObjectURL() after triggering the click().

Answered By: Louis Nguyen