node-ftp icon indicating copy to clipboard operation
node-ftp copied to clipboard

Stream in get() method's callback never emits the 'close' event

Open alyhegazy opened this issue 6 years ago • 7 comments

alyhegazy avatar Jan 03 '19 20:01 alyhegazy

Having the same problem. Seems to be that it's not writing the last bytes either because after it stops writing, the files I'm downloading are corrupt.

lironpls avatar Jan 13 '19 16:01 lironpls

Same problem here. My FTP server in use is vsFTPd 2.2.2. As far as I can tell the problem lies in the handling of the reply code 150 of the RETR command. Reading the code in connection.js the comments suggest another reply will be send. The code maintains for some reasons unknown to me a few (smelly) flags like done and last_reply. The event emitter swallows an 'end' event from the TLSSocket due to these flags.

My knowledge about the FTP protocol is very limited, I don't know whether the client of the server breaks the rules here.

I use a workaround to fetch the size of the file first and then signal the end of the stream myself by counting the bytes and comparing with the expected amount. My files are relatively small, so buffering is no issue.

reitsma avatar Apr 16 '19 07:04 reitsma

I have the same problem:

[connection] PASV socket connected
[connection] > 'RETR /data/example.json'
[connection] < '150 Opening BINARY mode data connection for /data/example.json (317 bytes)\r\n'
[parser] < '150 Opening BINARY mode data connection for /data/example.json (317 bytes)\r\n'
[parser] Response: code=150, buffer='Opening BINARY mode data connection for /data/example.json (317 bytes)'
data <Buffer 7b 0a 20 20 20 20 22 6e 61 6d 65 22 3a 20 22 65 78 61 6d 70 6c 65 22 2c 0a 20 20 20 20 22 6e 75 6c 6c 22 3a 20 6e 75 6c 6c 2c 0a 20 20 20 20 22 62 6f ... 267 more bytes>
length 317

After this output it hangs. My code is:

    ftp.on('ready', function() {
        console.log('ready');
        ftp.get(parsedUri.pathname, function(err, stream) {
            if (err) {
                ftp.end();
                return reject(err);
            }
            const bufs: any = [];
            stream.once('close', function() {
                console.log('close');
                ftp.end();
                resolve(Buffer.concat(bufs));
            });
            stream.on('data', d => {
                console.log('data', d)
                console.log('length', d.length);
                bufs.push(d);
            });
        });
    });
    ftp.connect({
        host: parsedUri.host,
        port: parsedUri.port ? Number(parsedUri.port) : undefined,
        user: parsedUri.username,
        password: parsedUri.password,
        // @ts-ignore
        debug: console.log
    });

Why is the stream not closed?

alinex avatar Apr 27 '19 17:04 alinex

I got it but only using another library: basic-ftp

alinex avatar Apr 27 '19 18:04 alinex

I have the exact same problem, also with a vsFTPd server... close event is never emitted :(

rpesciotta avatar May 21 '19 20:05 rpesciotta

I got it but only using another library: basic-ftp

@alinex do you mind sharing the code you got working using basic-ftp ?

astr0-4 avatar May 07 '20 02:05 astr0-4

I also had same problem when file finished downloading, I tried calling "ftp.end()" but it never finished so it stuck, when you called it "ftp.connect ()" again and checked "netstat -tan | grep :21" network is still connected even though we previously called ftp.end()

akbaryahya avatar Sep 10 '20 02:09 akbaryahya