【问题标题】:Download file on ajax success node.js在 ajax 成功 node.js 上下载文件
【发布时间】:2016-05-11 21:30:21
【问题描述】:

我正在使用 node.js 构建一个需要允许用户下载 .csv 文件的应用程序。

问题 - 当用户单击按钮时,应用程序不会将文件作为附件发送到客户端。但是,如果客户端直接访问 API 链接,则会下载该文件。例如。 - 如果用户转到localhost:3000/api/exportmetric,文件将作为附件发送给客户端。但是,如果该路由作为 AJAX 请求被命中,则不会发生任何事情。

用户流量:

1) 用户点击按钮

2) 应用向服务器发出 AJAX GET 请求

3) 服务器从数据库中检索数据

4) 服务器将数据解析成 .csv 文件

5) 服务器将文件发送回客户端以作为附件下载。

我的代码:

client.js

$("#export_velocity").click(function(e) {
    console.log('export to velocity hit');
    $.ajax({
        url: 'http://localhost:3001/api/exportmetric',
        type: 'GET',
        success: function(response) {
            console.log(response);
        },
        error: function(a, b, c) {
            console.log(a);
            console.log(b);
            console.log(c);
        }
    });
});

server.js

router.get('/api/exportmetric', function(req, res) {
    console.log('export metric hit');
    var fields = ['first_name', 'last_name', 'age'];
    var fieldNames = ['First Name', 'Last Name', 'Age??'];
    var people = [
      {
        "first_name": "George",
        "last_name": "Lopez",
        "age": "31"
      }, {
        "first_name": "John",
        "last_name": "Doe",
        "age": "15"
      }, {
        "first_name": "Jenna",
        "last_name": "Grassley",
        "age": "44"
      }
    ];

    json2csv({ data: people, fields: fields, fieldNames: fieldNames }, function(err, csv) {
      res.setHeader('Content-disposition', 'attachment; filename=file.csv');
      res.set('Content-Type', 'text/csv');
      console.log(csv)
      res.status(200).send(csv);
    });
});

【问题讨论】:

  • 不使用 ajax。 <a href="http://localhost:3001/api/exportmetric">Download CSV!</a>别想太多了!
  • 对,但最终我将需要使用 AJAX 将数据发送到我的服务器以查询需要下载到 csv 文件中的某些类型的数据
  • 您也可以使用 GET 和锚标记发送数据。不少于 ajax 允许的数据。
  • 使用ajax的问题​​是不能直接下载ajax请求的响应。相反,您必须将其设置为一个两步过程,服务器存储文件并将 URL 发送到客户端以供下载,然后在下载完成后将其删除,这有点复杂。到那时,再次删除 ajax 并进行表单发布或访问 iframe 会更容易
  • 我明白了,你能澄清一下send data with GET and an anchor tag吗?或者指出我在哪里可以找到有关它的更多信息?

标签: jquery ajax node.js csv


【解决方案1】:

下载文件基本上有两种流行的方式。

1.设置window.location

window.location设置为下载地址将下载文件。

window.location = '/path/to/download?arg=1';

一个稍微不同的版本是打开一个带有下载路径的新标签

window.open('/path/to/download', '_self');

2。虚拟链接点击

使用 HTML5,您可以指定链接的download 属性。单击链接(甚至以编程方式)将触发 url 的下载。链接甚至不需要成为 DOM 的一部分,您可以动态创建它们。

var link = document.createElement('a');
link.href = '/path/to/download';
link.download = 'local_filename.csv';
var e = document.createEvent('MouseEvents');
e.initEvent('click', true, true);
link.dispatchEvent(e);

并非所有浏览器都支持此方法,因此即使您想使用此方法,也必须放弃对某些浏览器的支持或回退到第一种方法。

幸运的是,this excellent answer 引用了一个很棒的小 js 库,它已经完成了所有这些工作 -- http://pixelscommander.com/polygon/downloadjs/#.VrGw3vkrKHv

downloadFile('/path/to/download');

两步下载

您经常看到的另一个约定是两步下载,其中信息通过已知 url 发送到服务器,然后服务器发回生成的 url 或 id 可用于下载文件。

如果您希望 url 成为可以共享的内容,或者您​​必须将大量参数传递给下载生成器,或者只是想通过 POST 请求来完成,这可能会很有用。

$.ajax({
    type: 'POST',
    url: '/download/path/generator',
    data: {'arg': 1, 'params': 'foo'},
    success: function(data, textStatus, request) {
        var download_id = data['id'];
        // Could also use the link-click method.
        window.location = '/path/to/download?id=' + download_id;
    }
});

【讨论】:

    【解决方案2】:

    为了补充 Brendan 的回答,我想出了第三种可行的方法:

    1 - 在 DOM 中创建一个临时表单

    2 - 用我们想要发布的数据填写表格(如在发布请求中)

    3 - 发送表格

    4 - 从 DOM 中删除表单

    这是我在 JS 中的做法

      $("#buybtn").click(function(){
        url = "localhost:8080/";
        // we create a form
        var form = document.createElement("form");
        // set the method to Post
        form.setAttribute("method", "post");
        // we set the action to be performed
        form.setAttribute("action", url + "api2");
    
        // the following variables contains the data to send
        params = {
            name : "name",
            age : "age"
        };
    
        // we iterate over the available fields in params
        // and set the data as if we are manually filling the form
        for(var key in params) {
            if(params.hasOwnProperty(key)) {
                var hiddenField = document.createElement("input");
                hiddenField.setAttribute("type", "hidden");
                hiddenField.setAttribute("name", key);
                hiddenField.setAttribute("value", params[key]);
    
                // we insert each element in the form
                form.appendChild(hiddenField);
            }
        }
    
        // we append the form to the DOM
        document.body.appendChild(form);
        // we submit the form
        form.submit();
        // we delete the created elements
        document.body.removeChild(form);
      });
    

    在这篇文章中感谢 Rakesh Pai:JavaScript post request like a form submit

    我希望它也对你有用!

    【讨论】:

      猜你喜欢
      • 2012-04-26
      • 1970-01-01
      • 1970-01-01
      • 2017-01-22
      • 2020-08-27
      • 2013-11-14
      • 1970-01-01
      • 1970-01-01
      • 2015-09-19
      相关资源
      最近更新 更多