简体   繁体   中英

Node FTP: Multiple asynchronous calls inside loop

I know this is some async conundrum I have gotten myself into, but I am trying to download multiple files, inside the callback from the .list method of any of npm's various FTP packages.

So something like this (note: JSFTP here is just a wrapper around node-ftp , I get the same issue with that one):

  ftp = new JSFTP(conf.FTPConfig)
  ftp.ls(conf.remoteFolder, (err, fileList) => {
    if (err) return console.error(err)

    for (let i=0; i<fileList.length; i++){
      file = fileList[i]
      ftp.get(file.name, `./Downloaded/${file.name}`, err => {
        if (err) return console.error(err)
        console.log(`${file.name} copied.`)
      })
    }
  })

If I don't use a loop and only download one file, everything works fine. But with a loop, I keep getting the following errors and I don't get any of the files (except one or two empty file placeholders):

(In short): Error: 503 Bad sequence of commands , and further below: 'Probably trying a PASV operation while one is in progress

It looks like it kicks off all my .get calls inside the loop (obviously without waiting for any of them to finish, which is fine), but then fails to actually execute all the .get calls this way? Should they not just run in parallel, asynchronously?

{ Error: 503 Bad sequence of commands.
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11)
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8)
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24)
    at emitOne (events.js:96:13)
    at Stream.emit (events.js:188:7)
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25)
    at emitOne (events.js:96:13)
    at ResponseParser.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:172:18)
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 }
{ Error: 503 Bad sequence of commands.
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11)
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8)
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24)
    at emitOne (events.js:96:13)
    at Stream.emit (events.js:188:7)
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25)
    at emitOne (events.js:96:13)
    at ResponseParser.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:172:18)
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 }
{ Error: 503 Bad sequence of commands.
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11)
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8)
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24)
    at emitOne (events.js:96:13)
    at Stream.emit (events.js:188:7)
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25)
    at emitOne (events.js:96:13)
    at ResponseParser.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:172:18)
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 }
{ Error: 503 Bad sequence of commands.
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11)
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8)
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24)
    at emitOne (events.js:96:13)
    at Stream.emit (events.js:188:7)
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25)
    at emitOne (events.js:96:13)
    at ResponseParser.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:172:18)
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 }
{ Error: 503 Bad sequence of commands.
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11)
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8)
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24)
    at emitOne (events.js:96:13)
    at Stream.emit (events.js:188:7)
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25)
    at emitOne (events.js:96:13)
    at ResponseParser.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:172:18)
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 }
{ Error: 503 Bad sequence of commands.
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11)
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8)
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24)
    at emitOne (events.js:96:13)
    at Stream.emit (events.js:188:7)
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25)
    at emitOne (events.js:96:13)
    at ResponseParser.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:172:18)
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 }
{ Error: connect ECONNREFUSED 192.168.100.161:61229
    at Object.exports._errnoException (util.js:1007:11)
    at exports._exceptionWithHostPort (util.js:1030:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14)
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: '192.168.100.161',
  port: 61229,
  msg: 'Probably trying a PASV operation while one is in progress' }

After looking at the source for jsftp it appears that is creates a single connection and uses just one socket: https://github.com/sergi/jsftp/blob/master/lib/jsftp.js#L120

This means that it does not create a new connection for each command, but uses a single connection to send the commands through. Basically how you can circumvent that is by creating a new SFTP instance for each file that you want to upload.

Basically reworking the code to this:

 ftp = new JSFTP(conf.FTPConfig) ftp.ls(conf.remoteFolder, (err, fileList) => { if (err) return console.error(err) for (let i=0; i<fileList.length; i++){ file = fileList[i] new JSFTP(conf.FTPConfig).get(file.name, `./Downloaded/${file.name}`, err => { if (err) return console.error(err) console.log(`${file.name} copied.`) }) } }) 

However I would recommend using some sort of a flow control library such as async or utilizing a promise based solution as it might be a little more manageable.

There is also a similar question on SO with a similar solution using the async module I mentioned: Downloading multiple file from ftp site using node js

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