Javascript 使用Ajax和Flask下载excel

Javascript 使用Ajax和Flask下载excel,javascript,python,jquery,ajax,flask,Javascript,Python,Jquery,Ajax,Flask,我正在尝试使用Ajax调用从flask下载excel。它将响应代码显示为200,但excel未下载,错误消息如下 Ajax请求: $(#genExcel”)。在(“单击”,函数()上{ var xhttp=newXMLHttpRequest() 烧瓶功能: @app.route('/genexcel', methods=["GET", "POST"]) def createExcel(): if request.method == 'POST': data = reque

我正在尝试使用Ajax调用从flask下载excel。它将响应代码显示为200,但excel未下载,错误消息如下

Ajax请求:

$(#genExcel”)。在(“单击”,函数()上{ var xhttp=newXMLHttpRequest()

烧瓶功能:

@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)
错误:

1[仅报告]拒绝将字符串作为JavaScript求值,因为“不安全评估”不是以下内容安全策略指令中允许的脚本源:“script src*blob:”。 2未捕获的TypeError:未能对“URL”执行“createObjectURL”:未找到与提供的签名匹配的函数。

这里是一个使用fetch API的示例。第一个按钮只是直接进行JS下载。第二个按钮使用Flask路由进行下载。希望对您有所帮助

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>

<!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>


希望我理解正确。下面是一个使用您提供的数据数组的非常简单的示例。您可以根据需要进行修改:

烧瓶功能

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");

    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>

<!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>


试验
测试
直接下载
烧瓶下载
var btn=document.getElementById(“genExcel”);
var btnFlask=document.getElementById(“genExcelFlask”);
变量数据数组={
数据:[
[1,“A”,100],
[2,“B”,200],
],
};
btn.addEventListener(“单击”,(e)=>{
取回(“https://jsonplaceholder.typicode.com/todos/1")
.然后((resp)=>resp.blob())
.然后((blob)=>{
constURL=window.url.createObjectURL(blob);
常量a=document.createElement(“a”);
a、 style.display=“无”;
a、 href=url;
//您想要的文件名
a、 下载=“todo-1.json”;
文件.正文.附件(a);
a、 单击();
window.URL.revokeObjectURL(URL);
警告(“您的文件已下载!”;//或者您知道,具有更好用户体验的内容。。。
})
.catch(()=>警惕(“哦,不!”);
});
btnFlask.addEventListener(“单击”,(e)=>{
log(JSON.stringify(dataArray));
获取(“{url\u for('createExcel')}}}”{
方法:“张贴”,
正文:JSON.stringify(dataArray),
})
.然后((resp)=>resp.blob())
.然后((blob)=>{
constURL=window.url.createObjectURL(blob);
常量a=document.createElement(“a”);
a、 style.display=“无”;
a、 href=url;
//您想要的文件名
a、 下载=“test.xlsx”;
文件.正文.附件(a);
a、 单击();
window.URL.revokeObjectURL(URL);
警告(“您的文件已下载!”;//或者您知道,具有更好用户体验的内容。。。
})
.catch(()=>警惕(“哦,不!”);
});

它正在下载excel,并显示警告消息,因为文件已损坏。在我的代码中..我正在将数组传递给flask函数,并将该数据插入excel,然后下载。您是否可以尝试将js数组数据传递给flask函数,并从内存中而不是从物理位置生成excel。?因此您希望js传递am数组到flask函数。在该函数中,您希望获取传递给它的数据并将其放入新的excel文件中,然后返回要下载的excel文件…正确吗?您有数组数据的示例吗?是的。我希望传递数组数据,并应将其动态插入excel,无需从中读取excelphysical path.example数组是一个嵌套数组,例如:dataArray=[[1,a,100],[2,B,200]]在输出excel中,每个数组都将插入excel的一行。@p-s-rao对您有效吗?我是否正确理解您的请求?添加标题后:{“内容类型”:“应用程序/json”}在fetch方法中,它正在工作。在flask函数中,而不是物理路径中,我将文件保存在内存中,用户可以使用它。非常感谢。
<!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>