简体   繁体   中英

File Download and Client Disconnection?

Given the following code:

async function (req, res, next) {
  const fd = await fs.open("myfile.txt")
  fs.createReadStream(null, { fd, autoClose: false })
    .on('error', next)
    .on('end', () => fs.close(fd))
    .pipe(res)
}

What happens if the client disconnects before downloading the entire file? ie will end still be called or is the file descriptor leaked, and if so how can I fix it? If `end´ is called does that mean that the entire file is read even though the client no longer listens for it?

Note, I know I could do this without fd but this is a simplification of more complex code.

It looks like file will not be closed, or at least your end event handler will not be called.

You can create test for that, but here's mine:

const http = require('http');
const fs   = require('fs');

var server = http.createServer(function (req, res) {
    console.log('server request received');
    const fd = fs.openSync('myfile.txt', 'r');
    fs.createReadStream(null, { fd, autoClose: false })
        .on('error', err => {
            console.error('file error', err);
        })
        .on('end', () => {
            console.log('file end');
            fs.close(fd);
        })
        .on('close', () => {
            console.log('file closed');
        })
        .pipe(res)
            .on('error', err => console.error('server stream error', err))
            .on('end', () => console.log('server stream end'))
            .on('close', () => console.log('server stream closed'))
    ;
});

server.listen(0, 'localhost', () => {
    const address = server.address();

    var req = http.request({port: address.port}, function (res) {
        res.on('data', data => {
            console.log('response data');
            // Comment next line to read whole file.
            req.abort();
        });
        res.on('end', () => {
            console.log('response ended');
            setTimeout(() => server.close(), 1000);
        });
        req.once('abort', () => {
            console.log('request aborted');
        });
    });

    req.end(() => {
        console.log('request sent');
    });
});

I removed async/wait for simplicity of running test.

When req.abort() is called, i get following output:

request sent
server request received
response data
request aborted
response ended
server stream closed

After commenting that line, and allowing code to read whole file:

request sent
server request received
response data
response data
response data
response data
response data
response data
file end
response data
response ended

To create test myfile.txt i used following command:

dd if=/dev/zero of=myfile.txt bs=1k count=200

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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