Max SchmittMS
4th April 2014

node.js FTP error: ECONNREFUSED

I'm currently experimenting with an idea for a project. For this, I had to write a script that recursively downloads a directory to my hard-drive using FTP.

I soon found out that when dealing with FTP and node.js, jsftp is the way to go as long as you don't need to support SFTP.

Recursively downloading an FTP-directory

Here is the steps I had in mind when writing my script:

  1. Authenticate via FTP
  2. Walk remote directory and save files/directories to an array
  3. Iterate through array and download files

Points 1 and 2 worked intuitively by writing a recursive function that uses jsftp's ftp.ls-function to walk the remote directory.

I thought I could now just iterate through the directory-listing that I had saved to an array and download each file. In code, this looked something like this:

remoteFiles.forEach(function(file) {
ftp.get(file.path, targetPath, function(err) {
if (err) return cb(err)
console.log('downloaded ' + file.path)
cb()
})
})

FTP error: ECONNREFUSED

However, nothing really happened. All I got, was a big, confusing (to me at least) error called ECONNREFUSED. I did a bit of Googling and read some stuff about firewalls but that wasn't the issue.

The issue was: I was creating too many connections to the ftp-server simultaneously.

Limiting ftp connections with jsftp

jsftp doesn't have a built-in functionality for limiting the number of concurrent connections, but it's still really easy by using the async-library.

There's a method called eachLimit that does just what we want. Everything works fine if we do something like this:

async.eachLimit(
remoteFiles,
1,
function(file, cb) {
ftp.get(file.path, targetPath, function(err) {
if (err) return cb(err)
console.log('downloaded ' + file.path)
cb()
})
},
function(err) {
if (err) return console.log(err)
console.log('all files were downloaded')
}
)

Of course there's some more logic required for dealing with "downloading" directories but the eachLimit-approach should solve your problems when dealing with the ECONNREFUSED-error in this case.

Image of my head

About the author

Hi, I’m Max! I'm a fullstack JavaScript developer living in Berlin.

When I’m not working on one of my personal projects, writing blog posts or making YouTube videos, I help my clients bring their ideas to life as a freelance web developer.

If you need help on a project, please reach out and let's work together.

To stay updated with new blog posts, follow me on Twitter or subscribe to my RSS feed.