0

我正在使用 ExpressJS 开发一个网络应用程序。

页面上有一个创建按钮。我想要实现的是,当单击按钮时,它会向服务器端发送一个 Post/Get 请求,然后服务器端会触发一个进程来生成一个 CSV 文件并将其发送回客户端进行下载。

我正在考虑使用json2csv.

客户端:

$.ajax({
            type: "POST",
            url: "/incidents/createTable",
            success: function() {
                // HOW TO GET THE RETURNED DATA TO A DOWNLOADABLE FILE?
            }
        });

服务器端和incidents路由器(下面的代码片段是从 json2csv 官方 npmjs 页面复制的):

const { AsyncParser } = require('json2csv');
// THIS FUNCTION SHOULD GENERATE A CSV FILE IN MEMORY
router.post("/createTable", async function(req, res, next) {
    console.log("flag 1");  // For flagging

    const fields = ['field1', 'field2', 'field3'];
    const opts = { fields };
    const transformOpts = { highWaterMark: 8192 };

    const asyncParser = new AsyncParser(opts, transformOpts);

    console.log("flag 2");  // For flagging
    let csv = '';
    asyncParser.processor
    .on('data', chunk => (csv += chunk.toString()))
    .on('end', () => res.send(csv))
    .on('error', err => console.error(err));
});

当我运行 Web 应用程序并单击“创建”按钮时,服务器挂在那里,它通过了“标志 2”并且从未通过asyncParser.processor. 在客户端,POST 请求也被挂在那里并且没有状态码。

4

2 回答 2

1

经过大量挖掘后终于找到了解决方案。

服务器端:

var stream = require('stream');
//...
router.post("/createTable", async function(req, res, next) {
    var fileContents = Buffer.from(JSON.stringify({
        sampleTime: '1450632410296',
        sampleData: '1234567890'
    }));

    var readStream = new stream.PassThrough();
    readStream.end(fileContents);

    res.set('Content-disposition', 'attachment; filename=' + "download.csv");
    res.set('Content-Type', 'text/csv');

    readStream.pipe(res);
});

客户端:

 $.ajax({
        type: "POST",
        url: "/incidents/createTable",
        success: function(result) {
            var blob=new Blob([result], {type: 'text/csv'});
            var link=document.createElement('a');

            link.style = "display: none";
            document.body.appendChild(link);

            var url = window.URL.createObjectURL(blob);
            link.href = url;
            console.log(url);
            link.download="download.csv";
            link.click();
            window.URL.revokeObjectURL(url);
        }
    });
于 2019-08-26T00:48:32.753 回答
0

您缺少一个部分,即提供数据。在您这样做之前,解析器不会做任何事情。这也是挂断请求,因为res.send永远都达不到。

就在文档中:

asyncParser.input.push(data); // This data might come from an HTTP request, etc.
asyncParser.input.push(null); // Sending `null` to a stream signal that no more data is expected and ends it.

这是将产生的完整代码

"field1","field2","field3"
1,2,3

在 GET /createTable 上

const { AsyncParser } = require('json2csv');
const express = require('express');

const app = express();

app.get("/createTable", async function(req, res, next) {
    console.log("flag 1");  // For flagging

    const fields = ['field1', 'field2', 'field3'];
    const opts = { fields };
    const transformOpts = { highWaterMark: 8192 };

    const asyncParser = new AsyncParser(opts, transformOpts);

    console.log("flag 2");  // For flagging
    let csv = '';
    asyncParser.processor
      .on('data', chunk => (csv += chunk.toString()))
      .on('end', () => res.send(csv))
      .on('error', err => console.error(err));

    asyncParser.input.push('{ "field1": 1, "field2": 2, "field3": 3 }');
    asyncParser.input.push(null); // Sending `null` to a stream signal that no more data is expected and ends it.
});

app.listen(3000);
于 2019-08-23T08:00:31.593 回答