1

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?

RishiC
  • 686
  • 9
  • 29
  • If you're trying to get an ajax request to handle something as a downloadable attachment, you'll need to use something along these lines: https://stackoverflow.com/questions/32545632/how-can-i-download-a-file-using-window-fetch – clockwatcher Jun 19 '20 at 18:48

2 Answers2

0

You can do the below

return send_from_directory(dir, file_name, as_attachment=True)

This will download the file on the user's machine.

Edit:

BTW, if you create an html form like below, you do not need javascript.

<form action='action here' method='post'>
    <input type='submit'>
</form>
KetZoomer
  • 2,258
  • 2
  • 11
  • 33
  • I tried send_from_directory as well...it did not work. As for the HTML, the data I want to send is in a different section, so I cant get it inside the form – RishiC Jun 19 '20 at 17:18
  • Okay. Can you be more specific about what happened. What error shows. It can be helpful to do: app.run(debug=True) – KetZoomer Jun 19 '20 at 17:55
  • There wasnt any error, I clicked the button,and nothing happened – RishiC Jun 20 '20 at 03:40
0

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

RishiC
  • 686
  • 9
  • 29