huggie
huggie

Reputation: 18237

Download file with Vue.js and Python Flask

My Flask is a REST server.

On my flask route this is what I have:

@app.route('/v1/download', methods=['POST'])
def download_tissue():
    f = open('path_to_zip_file', 'rb') // or r for text file
    return f.read()

(Previously I was using Flask's send_file(). But I'm not sure what send_file does that I can't do with just reading it, and I'm trying to simplify the case to figure out the problem.)

On the client I have a Vue application making an async request:

axios.post('download')
.then((res) => {
    let data = res.data;
    const blob = new Blob([data], { type: 'application/zip' })
    let link = document.createElement('a')
    link.href = window.URL.createObjectURL(blob)
    link.download = 'test.zip'
    link.click()
})
.catch(error => {
    console.error(error);
});

The problem is I can't unzip it on a Mac. Unable to expand test.zip in to Download. (Error 1 - Operation not permitted.) Also the file size is just wrong. It's nearly 22 mb instead of the original 12.

If I open plain text file it works, but not the zip file.

Upvotes: 5

Views: 3539

Answers (2)

huggie
huggie

Reputation: 18237

OK I figured it out. I actually need to configure axios response type like this:

axios({
        url: url
        method: 'POST',
        responseType: 'blob', // important
})
.then((res) => {
})

I actually would prefer to use the default URL setting, but the following didn't work for me.

axios.post('download', {
    responseType: 'blob',
})
.then((res) => {

Upvotes: 4

rabbit.aaron
rabbit.aaron

Reputation: 2579

I'm guessing you opened the file in byte mode, but when it's returned in the view function, Flask tries to decode it to a string, then encode back to bytes. That's why you get a bigger file.

try returning

flask.send_file("path/to/file.zip", mimetype="application/zip", as_attachment=True, attachment_filename="filenamefordownload.zip")

Upvotes: 0

Related Questions