我有一个NodeJS后端,用于侦听带有json包的POST请求。使用json包中的信息,它构建一个大约15,000行的csv文件,然后使用res.download将csv文件发送回客户端。
从云数据库读取到csv文件没问题。我检查了服务器中的文件,所有行都在那里,它们是准确的。但是,在客户端下载的文件可能会被切断几百行。似乎res.download()运行得太快,即使我已经明确地将流设置为一旦for循环结束或它正在运行时它应该但csv文件仍在缓冲或某事< / p>
这是我的代码:
服务器端:
app.post('/dashboard/download_data', function (req, res) {
let payload = req.body;
ref.orderByKey().once("value", function (snapshot) {
let data = snapshot.val();
writer.pipe(fs.createWriteStream('C:\\user\\EVCS_portal\\out.csv'));
for (let key in data) {
if (data.hasOwnProperty(key)) {
test_time = data[key]['time'];
writer.write({
time: data[key]['time'],
ac2p: data[key]['ac2p'],
dcp: data[key]['dctp']
})
}
}
writer.end('This is the end of writing\n');
writer.on('finish', () => {
console.log(test_time);
res.download('C:\\user\\EVCS_portal\\out.csv');
console.log('file sent out!')
});
})
客户端js:
firebase.auth().currentUser.getIdToken(true).then(function (idToken) {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let a = document.createElement('a');
a.href = window.URL.createObjectURL(xhr.response);
a.download = download_date + '.csv';
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
};
let url = "/dashboard/download_data";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.responseType = 'blob';
// Package our payload including the idToken and the date
let data = JSON.stringify({"idToken": idToken, 'date': download_date});
xhr.send(data);
答案 0 :(得分:1)
您没有收听'finish'
事件的正确信息流,这会导致您在csv写完之前发送回复。当res.download()
已完成将数据传输到流中时,您正在调用writer
,但那不是当csv WriteableStream
通过fs.createReadStream()
已完成将所有管道数据写入其中时流到文件系统。
不是在WriteableStream
中为csv创建pipe()
,而是将其保存在变量中并为'finish'
事件添加侦听器。在'finish'
上收听writer
会导致您的服务器在csv准备好之前做出响应。
app.post('/dashboard/download_data', function (req, res) {
let payload = req.body;
ref.orderByKey().once("value", function (snapshot) {
let data = snapshot.val();
let csvWriter = fs.createWriteStream('C:\\user\\EVCS_portal\\out.csv')
writer.pipe(csvWriter);
for (let key in data) {
if (data.hasOwnProperty(key)) {
test_time = data[key]['time'];
writer.write({
time: data[key]['time'],
ac2p: data[key]['ac2p'],
dcp: data[key]['dctp']
})
}
}
writer.end('This is the end of writing\n');
csvWriter.on('finish', () => {
console.log(test_time);
res.download('C:\\user\\EVCS_portal\\out.csv');
console.log('file sent out!')
});
})
})
答案 1 :(得分:-1)
服务器代码似乎没问题,但对于客户端代码来说似乎是让下载太快了。
请求查看此https://www.groupon.com/signup?metric=layout_login&return_to=https://www.groupon.com并尝试使用xhr.onload而不是xhr.onreadystatechange。