Javascript Express res.下载极其怪异的行为

Javascript Express res.下载极其怪异的行为,javascript,node.js,Javascript,Node.js,我有一个NodeJS后端,它使用json包侦听POST请求。它使用json包中的信息构建一个大约15000行的csv文件,然后使用res.download将csv文件发送回客户端 从云数据库读取csv文件没有问题。我已经检查了服务器上的文件,所有的行都在那里,它们都是准确的。但是,在客户端下载的文件可能会被截断几百行。似乎res.download()运行得太快了,尽管我已经显式地将流设置为在for循环结束后结束,或者在应该结束时运行,但csv文件仍在缓冲或其他 这是我的密码: 服务器端: app

我有一个NodeJS后端,它使用json包侦听POST请求。它使用json包中的信息构建一个大约15000行的csv文件,然后使用res.download将csv文件发送回客户端

从云数据库读取csv文件没有问题。我已经检查了服务器上的文件,所有的行都在那里,它们都是准确的。但是,在客户端下载的文件可能会被截断几百行。似乎res.download()运行得太快了,尽管我已经显式地将流设置为在for循环结束后结束,或者在应该结束时运行,但csv文件仍在缓冲或其他

这是我的密码:

服务器端:

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()
,但这不是当csv
WriteableStream
通过
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。请看一看:这很有意义,代码现在运行得很好。谢谢