下载 csv 文件作为对 AJAX 请求的响应

新手上路,请多包涵

我有一个名为“/downloadUserAction”的端点,用于收集数据并下载 csv 文件。我面临的挑战是,当使用按钮点击功能调用端点时,文件不会被下载,但只有当我直接在浏览器中访问端点时,它才会下载。

经过研究,我发现了无法使用 AJAX 下载文件的结论。这是有道理的,因为当我点击我的按钮时,我看到端点被点击并且文件内容被传递到网络选项卡中,但是没有文件被下载到客户端。

这就是我在 javascript 端使用我页面上的数据表按钮插件功能来调用我的端点的全部内容。

 $(document).ready(function () {
    var table = $("#userActivity").on('init.dt', function() {
            }).DataTable({
                dom: 'Blfrtip',
                buttons: [
                          {
                            extend: 'csvHtml5',
                            text: 'NLP Search Download',
                            action: function ( e, dt, node, config ) {
                                $.ajax({
                                    url : window.location + "/downloadUserAction?draw=3&search%5Bvalue%5D=NLP_SEARCH&order%5B0%5D%5Bcolumn%5D=6&order%5B0%5D%5Bdir%5D=desc"
                                });
                            }
                          }
                      ],

是否有另一种调用我的端点的方法会强制在客户端页面上下载?

旁注:我的数据表正在使用服务器端处理,否则我只会使用数据表 csv 导出按钮。

原文由 Daniel Gebrahanus 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 732
2 个回答

在现代浏览器中,您可以通过使用文件内容创建一个 Blob(在您的情况下由 Ajax 接收)、为其创建一个 URL 并使用 download 属性来提示下载:

 const saveData = (function () {
    const a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (data, fileName) {
        const blob = new Blob([data], {type: "octet/stream"}),
            url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
    };
}());

const data = 'a,b,c\n5,6,7',
    fileName = "my-csv.csv";

saveData(data, fileName);

JSFiddle

如果您的 Ajax 端点 URL 具有正确的标头(或者即使它不是只要您使用 download 属性),您可以放弃 Blob 和 Ajax,只需将 URL 添加到链接中下载属性。改编@pritesh 的代码,

 const saveData = (function () {
    const a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (url, fileName) {
        a.href = url;
        a.download = fileName;
        a.click();
    };
}());

const url = 'http://www.sample-videos.com/csv/Sample-Spreadsheet-10-rows.csv', // Replace with your own URL: window.location + "/downloadUserAction?draw=3&search%5Bvalue%5D=NLP_SEARCH&order%5B0%5D%5Bcolumn%5D=6&order%5B0%5D%5Bdir%5D=desc"
    fileName = "my-csv.csv";

saveData(url, fileName);

JSFiddle

原文由 Brett Zamir 发布,翻译遵循 CC BY-SA 3.0 许可协议

即使这是一个老问题,我也想发布我想出的答案,因为我遇到了同样的问题。

有一种替代方法可以直接在客户端使用 FileSaver.js 库保存 blob,而不是创建链接并调用 click 方法。

添加 FileSaver.js 后,您可以简单地使用 saveAS(blob, filename) 启动下载。

以下示例用于处理 Flask 服务器 send_file(file, as_attachment=True, attachment_filename='export.csv', mimetype='text/csv') 响应。

 function downloadCsv() {
  jQuery.ajax({
    async: true,
    url: URL,
    timeout: 5000,
    type: "post",
    xhrFields: {
      responseType: "blob", // to avoid binary data being mangled on charset conversion
    },
    data: postRequestdata,
    error: function (e) {
      console.error(e);
    },
    // in jQuery 1.4+ when the success callback its executed three arguments are passed (success(data, textStatus, XMLHttpRequest))
    success: function (blob, status, xhr) {
      // check for a filename
      var filename = "";
      var disposition = xhr.getResponseHeader("Content-Disposition");
      if(disposition && disposition.indexOf("filename") !== -1){
        splitted = disposition.split("filename=");
        filename = splitted[splitted.length-1];
        saveAs(blob, filename);
      }
    },
  });
}

原文由 Keyum 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏