How to create a sftp client with node.js (SSH2) in Electron Framework

How to create a sftp client with node.js (SSH2) in Electron Framework

With SSH2 library you'll be able to create a ssh connection to your server to transfer (download and upload) files easily. ssh2 is a SSH2 client module written in pure JavaScript for node.js. As electron framework is able to use node.js, you can use this plugin to create your own sftp client easily.

Requirements

To implement the sftp feature on our hybrid app, we'll need :

  • Node.js
  • SSH2 (written for Node.js)
  • Patience

Now let's get started !

Installation and setup

Add ssh2 as a dependency of your electron project, add it executing the following line in your Node.js command prompt:

npm install ssh2 --save

Then you'll be able to require it with Javascript using require("ssh2");

Creating a SFTP Client

The sftp client will be easy to set up after the installation of the ssh2 library, first you need to create a client (note that ssh2 doesn't support only sftp but more types, ssh ,ftp etc) using :

var Client = require('ssh2').Client;
var connection = new Client();

With the connection now the magic happens, to start a sftp connection, use the following code snippet. A connection object will be prepared and connected using the minimum configuration, then if the ssh connection is succesful, open a sftp connection !

var Client = require('ssh2').Client;
var connSettings = {
     host: 'myserver-direction.com',
     port: 22, // Normal is 22 port
     username: 'myUsername',
     password: 'myPassword'
     // You can use a key file too, read the ssh2 documentation
};

var conn = new Client();
conn.on('ready', function() {
    conn.sftp(function(err, sftp) {
         if (err) throw err;
         // you'll be able to use sftp here
         // Use sftp to execute tasks like .unlink or chmod etc
    });
}).connect(connSettings);

Listing a directory

To list a directory use the readdir method :

var Client = require('ssh2').Client;
var connSettings = {
     host: 'myserver-direction.com',
     port: 22, // Normal is 22 port
     username: 'myUsername',
     password: 'myPassword'
     // You can use a key file too, read the ssh2 documentation
};
var remotePathToList = '/var/www/ourcodeworld';

var conn = new Client();
conn.on('ready', function() {
    conn.sftp(function(err, sftp) {
         if (err) throw err;
         
         sftp.readdir(remotePathToList, function(err, list) {
                if (err) throw err;
                // List the directory in the console
                console.dir(list);
                // Do not forget to close the connection, otherwise you'll get troubles
                conn.end();
         });
    });
}).connect(connSettings);

The list variable is an array with objects, every object contains information about every folder and file inside the remote path. The structure should look like :

Uploading a file

To upload a file, you'll need to use the createWriteStream method. It will create a file with the providen name with the content of a local file. To provide the local file we'll use the local filesystem (require("fs")) and use the createReadStream method.

var Client = require('ssh2').Client;
var connSettings = {
     host: 'myserver-direction.com',
     port: 22, // Normal is 22 port
     username: 'myUsername',
     password: 'myPassword'
     // You can use a key file too, read the ssh2 documentation
};
var remotePathToList = '/var/www/ourcodeworld';

var conn = new Client();
conn.on('ready', function() {
    conn.sftp(function(err, sftp) {
         if (err) throw err;
         
        var fs = require("fs"); // Use node filesystem
        var readStream = fs.createReadStream( "path-to-local-file.txt" );
        var writeStream = sftp.createWriteStream( "path-to-remote-file.txt" );

        writeStream.on('close',function () {
            console.log( "- file transferred succesfully" );
        });

        writeStream.on('end', function () {
            console.log( "sftp connection closed" );
            conn.close();
        });

        // initiate transfer of file
        readStream.pipe( writeStream );
    });
}).connect(connSettings);

Delete a remote file

To delete a file, we'll use the unlink method. This method expects the remote file path as first parameter and a callback.

var Client = require('ssh2').Client;
var connSettings = {
     host: 'myserver-direction.com',
     port: 22, // Normal is 22 port
     username: 'myUsername',
     password: 'myPassword'
     // You can use a key file too, read the ssh2 documentation
};
var remotePathToList = '/var/www/ourcodeworld';

var conn = new Client();
conn.on('ready', function() {
    conn.sftp(function(err, sftp) {
         if (err) throw err;
         
         sftp.unlink("remote-filepath.txt", function(err){
            if ( err ) {
                console.log( "Error, problem starting SFTP: %s", err );
            }
            else
            {
                console.log( "file unlinked" );
            }

            conn.close();
        });
    });
}).connect(connSettings);

Changing permissions

To change the permissions of a remote file, we'll use the chmod method. This method expects the remote file path as first parameter and the permissions as second parameter, finally the callback as third parameter.

var Client = require('ssh2').Client;
var connSettings = {
     host: 'myserver-direction.com',
     port: 22, // Normal is 22 port
     username: 'myUsername',
     password: 'myPassword'
     // You can use a key file too, read the ssh2 documentation
};
var remotePathToList = '/var/www/ourcodeworld';

var conn = new Client();
conn.on('ready', function() {
    conn.sftp(function(err, sftp) {
         if (err) throw err;
         
         sftp.chmod( "remote-file-path.txt", 777, function(err){
                if ( err ) {
                    console.log( "Error, problem starting SFTP: %s", err );
                }
                else
                {
                    console.log( "Mode changed" );
                }
          });
    });
}).connect(connSettings);

With the previous example the file will have the 777 permissions. (rwxrwxrwx) No restrictions on permissions. Anybody may do anything. Generally not a desirable setting, just an example.

Final notes

There are a couple of details about the plugin that you may need to know:

  • The documentation can be found in the README.md file , but only with source code.
  • It does not have any kind of tests (unit or integration tests), however it works like a charm and that's important.

Have fun

Become a more social person