首页 > 解决方案 > 从后端下载 csv 文件

问题描述

我正在尝试创建一个 csv 文件并插入我的数据并从浏览器下载它。我正在 express js 后端中创建 csv 文件,并将链接发送到 react js 前端以通过浏览器下载。

我正在使用快速 csv 插件将数据写入 csv。这是我的代码。

async function dataToCSV(data) {
    var fileName = "report.csv";
    var ws = await fileSystem.createWriteStream('../' + fileName);
    var csv;
    await fastcsv.write(data, { headers: true }).on("finish", function () {
        console.log(ws);
        csv = "<a href='../report.csv' download='report.csv' id='download-link'></a>";
    }).pipe(ws);
    return csv;
}

从该方法获得输出后,我将其发送到前端。

return dataToCSV(jsonData).then((response) => {
            return {
                headers,
                statusCode: 200,
                body: response,
                type: 'binary'
            };
        }).catch((e) => {
            return {
                headers,
                statusCode: 400,
                body: {
                    error: e.message
                }
            };
        })

前端得到如下给出的响应。

<a href='report.csv' download='report.csv' id='download-link'></a>

然后我使用以下代码通过浏览器使用 react js 下载它。

 var div = document.createElement('div');
 div.innerHTML = response.trim();
 document.body.appendChild(div);
 var downloadLink = document.getElementById('download-link');
 if (downloadLink !== null) {
     downloadLink.click();
 }
 document.body.removeChild(div);

文件是在后端创建的,我可以确认。但是当它从浏览器下载时,它会失败。日志中没有错误。浏览器说

失败 - 没有文件

我不明白为什么它会失败。我认为响应是在创建文件之前发送到前端的,或者它无法识别创建文件的路径。但我不确定。请帮我找到解决方案。

标签: node.jsreactjsexpress

解决方案


.pipe()不会返回 Promise,因此您await不会做预期的事情。如果您想使用 Promises 等待流完成,请参阅stream.pipeline

可能还有其他因素在起作用 - 例如,您的 HTTP 处理程序看起来一点也不像express处理程序(即使您的问题包含“express”标签)。如果是无服务器函数(AWS Lambda?),您可能需要修改策略;根据平台,函数可能无法提供文件。

无论如何,最好构建一个 CSV 文件并将其直接发送到客户端,而不用写入文件系统,使用流(尽管在 AWS Lambda 上的 Node 中似乎不可能)。否则,始终可以将文件流式传输到云存储解决方案并为客户端提供预签名的 URL


推荐阅读