How to connect to SFTP in Node.js

By the time you are through with this post, we hope we’ve done our job by familiarizing you with writing Node.js code to ultimately be able to connect and interact with SFTP servers. SFTP is a commonly used standard, and secure protocol that focuses on safe file and data transfer. When setting up a connection with the server, there are a few steps required to complete; let's begin!

Run and Monitor Scheduled Tasks on your Favorite Apps
Cron To Go simplifies the monitoring, alerting, and management of your cron jobs' performance, uptime, and status - ensuring seamless operation.
Try Cron To Go for free!

Requirements

First things first: preparation. ssh2-sftp-client is an SFTP client for node.js, which serves as a wrapper around SSH2 to provide a high level abstraction for SFTP- related functionality. Once you are ready to install it, begin by manually running the following code:

npm install ssh2-sftp-client@^8.0.0

Or add a package.json file and declare your dependencies in it:

{
  "dependencies": {
    "ssh2-sftp-client": "^8.0.0"
  }
}

Then, run the following:

npm install

Connecting to SFTP

As an example for this post, we’ll be using an environment variable named SFTPTOGO_URL, which contains all of the information required to connect to an SFTP server in a URI format: sftp://user:password@host. The variable is parsed to extract the URI parts using URI.parse, and the remote server’s host key is verified by default using ~/.ssh/known_hosts.

let Client = require('ssh2-sftp-client');

class SFTPClient {
  constructor() {
    this.client = new Client();
  }

  async connect(options) {
    console.log(`Connecting to ${options.host}:${options.port}`);
    try {
      await this.client.connect(options);
    } catch (err) {
      console.log('Failed to connect:', err);
    }
  }

  async disconnect() {
    await this.client.end();
  }

}
connect.js

Listing Files

Once a working connection has been established, you may use it to list files on the remote SFTP server. This can be done by calling the ssh2-sftp-client’s list method and iterating over the returned array, which then corresponds to the files found in the path argument. In our example, our wrapper function simply prints out the files found in the remote path.

async listFiles(remoteDir, fileGlob) {
  console.log(`Listing ${remoteDir} ...`);
  let fileObjects;
  try {
    fileObjects = await this.client.list(remoteDir, fileGlob);
  } catch (err) {
    console.log('Listing failed:', err);
  }

  const fileNames = [];

  for (const file of fileObjects) {
    if (file.type === 'd') {
      console.log(`${new Date(file.modifyTime).toISOString()} PRE ${file.name}`);
    } else {
      console.log(`${new Date(file.modifyTime).toISOString()} ${file.size} ${file.name}`);
    }

    fileNames.push(file.name);
  }

  return fileNames;
}
listfiles.js

Upload File

The next step is to upload a file. Use the client object’s put function and pass the path to the local file and the remote path ( the file should also end up here after the upload). A function call would look like this: await client.uploadFile("./local.txt", "./remote.txt");

async uploadFile(localFile, remoteFile) {
  console.log(`Uploading ${localFile} to ${remoteFile} ...`);
  try {
    await this.client.put(localFile, remoteFile);
  } catch (err) {
    console.error('Uploading failed:', err);
  }
}
uploadfile.js

Download File

To finalize the process, you just need to download the files. Use the client object get function and pass the path to the remote file and the local path in which to store the downloaded file. You would call the function like so: await client.downloadFile("./remote.txt", "./download.txt");

async downloadFile(remoteFile, localFile) {
  console.log(`Downloading ${remoteFile} to ${localFile} ...`);
  try {
    await this.client.get(remoteFile, localFile);
  } catch (err) {
    console.error('Downloading failed:', err);
  }
}
downloadfile.js

The Whole Thing

After following the above steps, the process is complete! Lastly, if you would like to run the entire program from start to finish, copy the following code and save it as main.js:

// sftp.js
//
// Use this sample code to connect to your SFTP To Go server and run some file operations using Node.js.
//
// 1) Paste this code into a new file (sftp.js)
//
// 2) Install dependencies
//   npm install ssh2-sftp-client@^8.0.0
//
// 3) Run the script
//   node sftp.js
// 
// Compatible with Node.js >= v12
// Using ssh2-sftp-client v8.0.0

let Client = require('ssh2-sftp-client');

class SFTPClient {
  constructor() {
    this.client = new Client();
  }

  async connect(options) {
    console.log(`Connecting to ${options.host}:${options.port}`);
    try {
      await this.client.connect(options);
    } catch (err) {
      console.log('Failed to connect:', err);
    }
  }

  async disconnect() {
    await this.client.end();
  }

  async listFiles(remoteDir, fileGlob) {
    console.log(`Listing ${remoteDir} ...`);
    let fileObjects;
    try {
      fileObjects = await this.client.list(remoteDir, fileGlob);
    } catch (err) {
      console.log('Listing failed:', err);
    }

    const fileNames = [];

    for (const file of fileObjects) {
      if (file.type === 'd') {
        console.log(`${new Date(file.modifyTime).toISOString()} PRE ${file.name}`);
      } else {
        console.log(`${new Date(file.modifyTime).toISOString()} ${file.size} ${file.name}`);
      }

      fileNames.push(file.name);
    }

    return fileNames;
  }

  async uploadFile(localFile, remoteFile) {
    console.log(`Uploading ${localFile} to ${remoteFile} ...`);
    try {
      await this.client.put(localFile, remoteFile);
    } catch (err) {
      console.error('Uploading failed:', err);
    }
  }

  async downloadFile(remoteFile, localFile) {
    console.log(`Downloading ${remoteFile} to ${localFile} ...`);
    try {
      await this.client.get(remoteFile, localFile);
    } catch (err) {
      console.error('Downloading failed:', err);
    }
  }

  async deleteFile(remoteFile) {
    console.log(`Deleting ${remoteFile}`);
    try {
      await this.client.delete(remoteFile);
    } catch (err) {
      console.error('Deleting failed:', err);
    }
  }
}

(async () => {
  const parsedURL = new URL(process.env.SFTPTOGO_URL);
  const port = parsedURL.port || 22;
  const { host, username, password } = parsedURL;

  //* Open the connection
  const client = new SFTPClient();
  await client.connect({ host, port, username, password });

  //* List working directory files
  await client.listFiles(".");

  //* Upload local file to remote file
  await client.uploadFile("./local.txt", "./remote.txt");

  //* Download remote file to local file
  await client.downloadFile("./remote.txt", "./download.txt");

  //* Delete remote file
  await client.deleteFile("./remote.txt");

  //* Close the connection
  await client.disconnect();
})();
main.js

Finally, run it using the command:

node main.js

Congratulations on connecting to SFTP using Node.js!

Cloud FTP with maximum security and reliability
SFTP To Go offers managed cloud storage service - highly available, reliable and secure. Great for companies of any size, any scale.
Try SFTP To Go for free!

Check out more code samples on Github.