Javascript Express res.下载极其怪异的行为
我有一个NodeJS后端,它使用json包侦听POST请求。它使用json包中的信息构建一个大约15000行的csv文件,然后使用res.download将csv文件发送回客户端 从云数据库读取csv文件没有问题。我已经检查了服务器上的文件,所有的行都在那里,它们都是准确的。但是,在客户端下载的文件可能会被截断几百行。似乎res.download()运行得太快了,尽管我已经显式地将流设置为在for循环结束后结束,或者在应该结束时运行,但csv文件仍在缓冲或其他 这是我的密码: 服务器端:Javascript Express res.下载极其怪异的行为,javascript,node.js,Javascript,Node.js,我有一个NodeJS后端,它使用json包侦听POST请求。它使用json包中的信息构建一个大约15000行的csv文件,然后使用res.download将csv文件发送回客户端 从云数据库读取csv文件没有问题。我已经检查了服务器上的文件,所有的行都在那里,它们都是准确的。但是,在客户端下载的文件可能会被截断几百行。似乎res.download()运行得太快了,尽管我已经显式地将流设置为在for循环结束后结束,或者在应该结束时运行,但csv文件仍在缓冲或其他 这是我的密码: 服务器端: app
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);
服务器代码似乎还可以,但对于客户端代码来说,下载似乎太急了
请看一看,然后尝试xhr.onload而不是xhr.onreadystatechange。您没有听到正确的
'finish'
事件流,该事件导致您在csv完成写入之前发送响应。当writer
完成将数据传输到流时,您正在调用res.download()
,但这不是当csvWriteableStream
通过fs.createReadStream()
将其流中的所有管道数据写入文件系统时
不要在管道()中为csv创建WriteableStream
,而是将其保存在变量中,并为'finish'
事件添加侦听器。在writer
上侦听'finish'
会导致服务器在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!')
});
})
})
谢谢你的回复!我试过这个。我只是将onreadystatechange替换为onload,这种行为仍然存在。还有其他想法吗?我想另一件可能会影响volumn问题的事情是createObjectURL。请看一看:这很有意义,代码现在运行得很好。谢谢