簡體   English   中英

Express res.download非常奇怪的行為

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM