skip to Main Content

I’m trying to download the excel from flask using Ajax call. it’s showing the response code as 200 but excel is not downloading and the error messages are as follows.

Ajax Request :

$(“#genExcel”).on(“click”, function() {
var xhttp = new XMLHttpRequest();

                // Data to post
                var dataarray = {};

                // Use XMLHttpRequest instead of Jquery $ajax

                xhttp.onreadystatechange = function() {
                    var a;
                    if (xhttp.readyState === 4 && xhttp.status === 200) {
                        // Trick for making downloadable link
                        a = document.createElement('a');
                        const objectURL = window.URL.createObjectURL(xhttp.response);
                        a.href = objectURL

                        //const objectURL = URL.createObjectURL(object)

                        // Give filename you wish to download
                        a.download = "test-file.xlsx";
                        a.style.display = 'none';
                        document.body.appendChild(a);
                        a.click();
                    }
                };
                // Post data to URL which handles post request
                xhttp.open("POST", '/genexcel');
                xhttp.setRequestHeader("Content-Type", "application/json");
                // You should set responseType as blob for binary responses
                //xhttp.responseType = 'blob';
                xhttp.send(JSON.stringify(dataarray));
            });

Flask function :

@app.route('/genexcel', methods=["GET", "POST"])
def createExcel():
    if request.method == 'POST':
        data = request.json  
        # process json data        
        return send_file(strIO, attachment_filename='test.xlsx',  as_attachment=True)

Errors :

1 [Report Only] Refused to evaluate a string as JavaScript because ‘unsafe-eval’ is not an allowed source of script in the following Content Security Policy directive: “script-src * blob:”.

2 Uncaught TypeError: Failed to execute ‘createObjectURL’ on ‘URL’: No function was found that matched the signature provided.

at XMLHttpRequest.xhttp.onreadystatechange

error and response

2

Answers


  1. Here is an example using the fetch API. The first button just does a straight JS download. The second button uses the Flask route to do the download. Hope it helps.

    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Test</title>
      </head>
      <body>
        Testing
        <button id="genExcel">Direct Download</button>
        <button id="genExcelFlask">Flask Download</button>
      </body>
    
      <script>
        var btn = document.getElementById("genExcel");
        var btnFlask = document.getElementById("genExcelFlask");
    
        btn.addEventListener("click", (e) => {
          fetch("https://jsonplaceholder.typicode.com/todos/1")
            .then((resp) => resp.blob())
            .then((blob) => {
              const url = window.URL.createObjectURL(blob);
              const a = document.createElement("a");
              a.style.display = "none";
              a.href = url;
              // the filename you want
              a.download = "todo-1.json";
              document.body.appendChild(a);
              a.click();
              window.URL.revokeObjectURL(url);
              alert("your file has downloaded!"); // or you know, something with better UX...
            })
            .catch(() => alert("oh no!"));
        });
    
        btnFlask.addEventListener("click", (e) => {
          fetch("{{ url_for('createExcel') }}")
            .then((resp) => resp.blob())
            .then((blob) => {
              const url = window.URL.createObjectURL(blob);
              const a = document.createElement("a");
              a.style.display = "none";
              a.href = url;
              // the filename you want
              a.download = "test.xlsx";
              document.body.appendChild(a);
              a.click();
              window.URL.revokeObjectURL(url);
              alert("your file has downloaded!"); // or you know, something with better UX...
            })
            .catch(() => alert("oh no!"));
        });
      </script>
    </html>
    
    

    Flask Function

    from flask import Flask, render_template, request, url_for, send_file
    
    @app.route('/genexcel', methods=["GET", "POST"])
    def createExcel():
        if request.method == 'POST':
            data = request.json
            print(data)
            # process json data
    
        file_path = 'static/files/test.xlsx'
        return send_file(file_path, attachment_filename='test.xlsx', as_attachment=True)
    
    Login or Signup to reply.
  2. Hopefully I’ve understood you correctly. Here is a very simple example using the data Array you provided. You could modify to suit your needs:

    Flask Functions

    from flask import Flask, render_template, request, url_for, send_file
    import xlsxwriter
    
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    @app.route('/genexcel', methods=["GET", "POST"])
    def createExcel():
        if request.method == 'POST':
            data = request.get_json(force=True)
            # process json data
            createExcel(data['data'])
    
        file_path = 'static/files/test.xlsx'
        return send_file(file_path, attachment_filename='test.xlsx', as_attachment=True)
    
    def createExcel(data):
        workbook = xlsxwriter.Workbook('static/files/test.xlsx')
        worksheet = workbook.add_worksheet()
    
        row_no = 0
        col_no = 0
        for row in data:
            col_no = 0
            for entry in row:
                worksheet.write(row_no, col_no, entry)
                col_no += 1
            row_no += 1
    
        workbook.close()
    
    app.run(debug=True, port=5010)
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Test</title>
      </head>
      <body>
        Testing
        <button id="genExcel">Direct Download</button>
        <button id="genExcelFlask">Flask Download</button>
      </body>
    
      <script>
        var btn = document.getElementById("genExcel");
        var btnFlask = document.getElementById("genExcelFlask");
        var dataArray = {
          data: [
            [1, "A", 100],
            [2, "B", 200],
          ],
        };
    
        btn.addEventListener("click", (e) => {
          fetch("https://jsonplaceholder.typicode.com/todos/1")
            .then((resp) => resp.blob())
            .then((blob) => {
              const url = window.URL.createObjectURL(blob);
              const a = document.createElement("a");
              a.style.display = "none";
              a.href = url;
              // the filename you want
              a.download = "todo-1.json";
              document.body.appendChild(a);
              a.click();
              window.URL.revokeObjectURL(url);
              alert("your file has downloaded!"); // or you know, something with better UX...
            })
            .catch(() => alert("oh no!"));
        });
    
        btnFlask.addEventListener("click", (e) => {
          console.log(JSON.stringify(dataArray));
    
          fetch("{{ url_for('createExcel') }}", {
            method: "post",
            body: JSON.stringify(dataArray),
          })
            .then((resp) => resp.blob())
            .then((blob) => {
              const url = window.URL.createObjectURL(blob);
              const a = document.createElement("a");
              a.style.display = "none";
              a.href = url;
              // the filename you want
              a.download = "test.xlsx";
              document.body.appendChild(a);
              a.click();
              window.URL.revokeObjectURL(url);
              alert("your file has downloaded!"); // or you know, something with better UX...
            })
            .catch(() => alert("oh no!"));
        });
      </script>
    </html>
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search