Search code examples
javascriptpython-3.xflaskhttprequestfetch-api

Download file from server with Flask and JS


I am trying to download a file when a user clicks on a particular button. This file is an image which gets created when the said button is pressed. What I want is, it should automatically download the image on the client's device.

I am using Flask on the server code, and ideally, the send_file function of Flask should trigger this auto download as it adds the Content-Disposition header.

On the client side, I have a JS code which uses fetch API to send a POST request to the server with some data, which is used for generating the image which is to be downloaded.

This is the JS code:

function make_image(text){
    const json={
        text: text
    };
    const options={
        method: "POST",
        body: JSON.stringify(json),
        headers:{
            'Content-Type':'application/json',
        }
    };

    fetch('/image',options)
        .then(res=>{
            res.json(); //Gives an error: Uncaught (in promise) SyntaxError: Unexpected token � in JSON at position 0
        }).catch(err=>console.log(err));
}

And this is the Python code on the server:

@app.route('/image',methods=['POST'])
def generate_image():
    cont = request.get_json()
    t=cont['text']
    print(cont['text'])
    name = pic.create_image(t)
    time.sleep(2)
    return send_file(f"{name}.png",as_attachment=True,mimetype="image/png")

But nothing is happening. The image doesnt get downloaded. However,the image is getting created on the server and is not corrupt

How do I resolve this? And is there some other way to do what I am trying to do?


Solution

  • As @clockwatcher mentioned a different question, I used the download.js module to handle the download of the image.

    So my JS code looks like this now:

    function make_image(text){
        const json={
            text: text
        };
        const options={
            method: "POST",
            body: JSON.stringify(json),
            headers:{
                'Content-Type':'application/json',
            }
        };
    
        fetch('/image',options)
            .then(res=>{
                return res.blob();
            }).then(blob=>{
                download(blob)
            }).catch(err=>console.log(err));
    }
    

    And an addition to the script tag in the html:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/downloadjs/1.4.8/download.min.js"></script>

    With no change in the Python server code.

    It works now