简体   繁体   English

为什么从 node.js 服务器多次下载文件会导致空文件

[英]Why downloading a file from node.js server multiple times results in empty files

I am glad to get some help.我很高兴得到一些帮助。

Here is my problem:这是我的问题:

I have built a web server with node.js that should send a csv file to the client when requested through a certain route.我已经用 node.js 构建了一个 Web 服务器,当通过某个路由请求时,它应该向客户端发送一个 csv 文件。 The csv file is created from json using the fast-csv package. csv 文件是使用 fast-csv 包从 json 创建的。 The json data comes from a mongoDB and is processed with mongoose. json 数据来自 mongoDB,并使用 mongoose 进行处理。 When I request this route once, it works fine.当我请求此路线一次时,它工作正常。 However, when it is requested a second time, an empty file is sent to the client.但是,当第二次请求时,会向客户端发送一个空文件。 By the way, the headers reach the client correctly.顺便说一句,标头正确地到达了客户端。 I have to restart the server to download my file again.我必须重新启动服务器才能再次下载我的文件。

What did I try:我尝试了什么:

Basically, I have now lost track of everything I have tried.基本上,我现在已经忘记了我尝试过的所有事情。 This behavior occurs both when using postman and when querying via the browser.使用邮递员和通过浏览器查询时都会发生此行为。 I've tried implementing promises in my handler function.我已经尝试在我的处理函数中实现承诺。 I've tried to unsubscribe res somehow (but yes, that was a stupid approach).我试图以某种方式取消订阅 res(但是是的,这是一种愚蠢的方法)。 I`ve tried to write the file into the fs and to send it on a second request.我试图将文件写入 fs 并在第二次请求时发送它。 ... ...

Maybe one of you can tell what's going wrong here at first glance:也许你们中的一个人一眼就能看出这里出了什么问题:

const { format } = require("@fast-csv/format");
const csvStream = format({ delimiter: ";", headers: true });

const router = express.Router();

router.route("/:collection/csv").get(requireModel, createCsv);

const csvFromDatabase = (data, res) => {
  csvStream.pipe(res);

  const processData = (data) => {
    data.forEach((row) => {
      const { _id, __v, ...newRow } = row._doc;
      csvStream.write({ ...newRow });
    });
    csvStream.end();
  };
  processData(data);
};

const createCsv = async (req, res) => {
  const { model } = req;
  const items = await model.find({});
  res.setHeader("Content-disposition", "attachment; filename=file.csv");
  res.setHeader("Content-type", "text/html; charset=UTF-8");
  csvFromDatabase(items, res);
};

Thank you very much for your help.非常感谢您的帮助。 I hope I didn't bore you with too stupid questions.我希望我没有用太愚蠢的问题让你厌烦。

You need to recreate csvStream for each new request:您需要为每个新请求重新创建csvStream

const csvFromDatabase = (data, res) => {
  const csvStream = format({ delimiter: ";", headers: true });
  
  csvStream.pipe(res);
  …
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM