Jason Strimpel
Jason Strimpel

Reputation: 15476

Download Excel file with Ajax and Flask

User presses a button contained within a form on the page:

<form id="form">
    <input type="button" id="export" value="Export"/>
</form>

Upon clicking the button, the following Ajax call is made:

ajaxCall('/export', {}, callback_export, 'get');

Where

function ajaxCall(url, params, callback, type) {
    if (validate()) {
        var request;
        request = $.ajax({
            url: url,
            type: type,
            data: params
        });
    }
    request.done(function (response, textStatus, jqXHR){
        callback(response);
    });
}

The Flask app looks like this:

@app.route('/export')
def export():
    xl_file= '/absolute/path/to/excel/file.xlsx'
    return send_file(xl_file, as_attachment=True, mimetype='application/vnd.ms-excel')

The file contents of the file are being returned to the browser (see image below) but not the file itself as an attachment.

Question is, what does the callback need to look like to accept the response as a file attachment? Or otherwise, what modifications need to be made?

(Yes, I've searched and read many of the posts on SE. Most discussing using the form.submit() method but do not provide details. I'm hoping to avoid using form.submit() as there are other elements within the #form that cannot be submitted.)

enter image description here

Upvotes: 6

Views: 11060

Answers (3)

Alexandre Crivellaro
Alexandre Crivellaro

Reputation: 893

I have used a different approach, not Ajax, I have created a function to update the href with some parameter every time a selection changes it, in this case is the country_id.

HTML:

<a type="button" class="btn btn-sm" id="export-excel" href="#">Download</a>

In the script section I wrote:

function country_change(country_id)
{
   var param = "/export_excel?";
   param += "country_id=" + country_id;
   $("a[id='export-excel']").attr('href', param);
}

So when you click the button the href is already updated. My flask part is:

@app.route('/export_excel')
def export_excel ():
     country_id = request.args.get('country_id')
     obj = class_calc.calc()
     file_excel = obj.generate_excel(country_id)
     return send_file(file_excel, as_attachment=True, cache_timeout=0)

Works fine.

Upvotes: 0

Renaud
Renaud

Reputation: 16501

You can use Flask's send_from_directory function

@app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
def download(filename):
    return send_from_directory(directory='uploads', filename=filename)

Upvotes: 2

Carlos Neves
Carlos Neves

Reputation: 71

You really need to use ajax? I found ajax is a work around to download excel files with flask...but it didn't work for me. I simply open excel file in 'rb' mode and change mimetype to be recognised as excel file in windows. Your Flast only need to call getPlotExcel().

@app.route("/getPlotExcel")
def getPlotExcel():
    excelDownload = open("sample.xlsx",'rb').read()
    return Response(
        excelDownload,
        mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-disposition":
                 "attachment; filename=sample.xlsx"})

Upvotes: 7

Related Questions