res.end() 在将文件流式传输到客户端后永远不会发送

res.end() is never sent after streaming a file to client

我基本上是在尝试将文件从 MongoDb 流式传输到客户端。文件接收没有问题,但是当流结束并且我尝试发送 request.end() 时,客户端永远不会收到它。

app.post('/upload', function (req, res) {
    var db = new mongo.Db('prueba', new mongo.Server("127.0.0.1", 27017));
    db.open(function (err) {
        if (err) return handleError(err);

        var gfs = Grid(db, mongo);
        console.log(req.filename);
        var uploadedSize = 0,
            uploadProgress = 0;
        idPdf = new ObjectId();  //cliente crea un id de mongo, el cual se utilizara para traer el recurso despues
        console.log(idPdf);

        var grabarm = req.pipe(gfs.createWriteStream({
            filename: 'test',
            _id: idPdf
        }));

        grabarm.on("close", function () {

            var tbuffer = gfs.createReadStream({filename: 'test'});

            tbuffer.on('open', function () {
                // This just pipes the read stream to the response object (which goes to the client)
                res.setHeader('Content-disposition', 'attachment; filename=pdfmongo.pdf');
                res.setHeader('Content-type', 'application/pdf');

                tbuffer.pipe(res);
            });

            tbuffer.on('data', function (chunk) {
                console.log("receiving data");
            });
            tbuffer.on("close", function () {

                console.log("fin"); //can see it in console
                res.end("ok file received");//client never sees this

            });

            tbuffer.on('error', function (err) {
                res.end(err);
            });
        });

    });

});

当您的可读流完成读取时,默认情况下,它会发出 end() 事件,这将调用可写流(res 流)上的 end() 事件。在这种情况下,您无需担心调用 end()。

因此在调用 end() 事件后,您的资源将不再可写。所以,如果你想让它保持可写,只需将 end: false 选项传递给 pipe()。例如:

fs.createReadStream("./image.png").pipe(res, { end: false });

,稍后调用 end() 事件。

顺便说一句,您应该收听 'end' 事件而不是 'close' 事件以完成流,因为 'close' 并不明确表示所有数据都已传输。