mscdex / node-ftp

An FTP client module for node.js
MIT License
1.13k stars 246 forks source link

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

Open alyhegazy opened 5 years ago

lironpls commented 5 years ago

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.

reitsma commented 5 years ago

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.

alinex commented 5 years ago

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 commented 5 years ago

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

rpesciotta commented 5 years ago

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

astr0-4 commented 4 years ago

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

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

akbaryahya commented 3 years ago

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()