简体   繁体   中英

Receive xlsx file from Flask server on JS client

On my client, the user clicks on a button which then calls the function below. I followed some code of other questions asked on StackOverflow about creating a url for the file and then downloading it:

export const exportData = async (checked) => {
  let checked_arr = await exportDataHelper(checked)
  try {
    const res = await axios.post(local + "/get-files", checked_arr);
    const url = URL.createObjectURL(res.data)
    const link = document.createElement('a')
    link.download = true;
    link.href = url;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link)
    return res.data;
  } catch (err) {
    return err;
  }
}

My Flask server receives some data from my JS client and creates an excel file out of that data. As a response back to the client, I send that excel file via Flask's send_file:

@app.route("/get-files", methods=['POST'])
def get_files():
    if request.method == "POST":
        ..Creating excel file here..
            try:
                return send_file("newOutput.xlsx", as_attachment=True)
            except FileNotFoundError as e:
                return json.jsonify(message="Failed"), 404
        else:
            return json.jsonify(message="Failed"), 500
    return json.jsonify(message="Failed"), 500

When i do console.log(res.data) I see some gibbersih like this PK ? a]I:O [Content_Types].xml n 0 E *1tQU E \\ . It's longer but I won't paste the whole thing.

But the JS code does nothing else after. In fact, I tried logging something to the console after I create the const url , and nothing is being logged, it's like it is stuck there. Any help? I am trying to have the file downloaded on the client side.

This is for future people who stumble upon this problem. I did not test this answer with other file types such as .png .jpeg. txt. or any other type other than .xlsx, but I think it will still work as long as you change the mimetype .

I ended up splitting my requests, one POST request that sends the data to my Flask server from my JS client. And another FETCH request that asks for the created .xlsx file.

JS/React code:

export const exportData = async (checked) => {
  let checked_arr = await exportDataHelper(checked)
  try {
    const res = await axios.post(local + "/get-files", checked_arr);
    return res;
  } catch (err) {
    return err;
  }
}

export const fetchOutput = async () => {
  await fetch(local + '/fetch-output').then(res => res.blob()).then(blob=> {
    var file = new Blob([blob], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})
    var url = URL.createObjectURL(file)
    var link = document.createElement('a')
    link.download = "newOutput.xlsx";
    link.href = url;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link)
  })
}

Python/Flask code:

@app.route("/get-files", methods=['POST'])
def get_files():
    if request.method == "POST":
        ...some irrelevant code...
        res = create_output_excel(result)
        if res:
            try:
                return json.jsonify(message="Success"), 200
            except FileNotFoundError as e:
                return json.jsonify(message="Failed"), 404
        else:
            return json.jsonify(message="Failed"), 500
    return json.jsonify(message="Failed"), 500

@app.route("/fetch-output")
def fetch_output():
    return send_file("newOutput.xlsx", mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")

In my case, the output file will always have the same name, so of course if yours is variable then you must do the appropriate changes for that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM