[英]Express res.download extremely weird behaviour
我有一個NodeJS后端,它使用json包監聽POST請求。 利用json包中的信息,它構建了一個約15,000行的csv文件,然后使用res.download將csv文件發送回客戶端。
從雲數據庫讀取到csv文件沒有問題。 我已經檢查了服務器中的文件,並且所有的行都在那里,它們是准確的。 但是,在客戶端下載的文件可能會中斷幾百行。 即使我已經明確地將流設置為在for循環結束后結束或在應有的情況下仍在運行但csv文件仍在緩沖中時,res.download()似乎運行得太早
這是我的代碼:
服務器端:
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);
您沒有在聽'finish'
事件的正確流,這導致您在csv完成寫入之前發送響應。 你打電話res.download()
時, writer
已經管道完成數據的流,但那不是當CSV WriteableStream
通過fs.createReadStream()
已經寫完所有的數據管道在其流文件系統。
不用在pipe()
為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!')
});
})
})
服務器代碼似乎還可以,但是對於客戶端代碼而言,下載卻太急了。
請看一下該線程,然后嘗試使用xhr.onload而不是xhr.onreadystatechange。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.