user3045179
user3045179

Reputation: 331

SFTP Server for reading directory using node js

I have created a node based SSH2 SFTP Server and Client. My objective is to read directory structure of SFTP Server. Suppose I have an SFTP Server containing folder temp, I want to read files inside the temp directory. I am using ssh2 npm module for creating SFTP Server and Client. It is making connection to SFTP Server but not listing the directory

Below is the code

CLIENT SIDE SFTP

var Client = require('ssh2').Client;
var connSettings = {
     host: 'localhost',
     port: 22,
     username:'ankit',
     password:'shruti',
     method:'password'

     // You can use a key file too, read the ssh2 documentation
};

var conn = new Client();
conn.on('ready', function() {

console.log("connected to sftp server")

conn.sftp(function(err, sftp) {
        if (err) 
        throw err;

        sftp.readdir('',function(err,list)
        {

            console.log('Inside read')
            if(err)
            {
            console.log(err);    
            throw err;
            }
            console.log('showing directory listing')
            console.log(list);
            conn.end();

        })


        /** 
        var moveFrom = "/remote/file/path/file.txt";
        var moveTo = __dirname+'file1.txt';

        sftp.fastGet(moveFrom, moveTo , {}, function(downloadError){
            if(downloadError) throw downloadError;

            console.log("Succesfully uploaded");
        });
        */
 })

}).connect(connSettings);

SERVER SIDE SFTP : 

var constants = require('constants');
var fs = require('fs');

var ssh2 = require('ssh2');
var OPEN_MODE = ssh2.SFTP_OPEN_MODE;
var STATUS_CODE = ssh2.SFTP_STATUS_CODE;

var srv = new ssh2.Server({
  hostKeys: [fs.readFileSync(__dirname+'/key/id_rsa')],debug:console.log
}, function(client) {
  console.log('Client connected!');
   client.on('authentication', function(ctx) {
    if (ctx.method === 'password'
        // Note: Don't do this in production code, see
        // https://www.brendanlong.com/timing-attacks-and-usernames.html
        // In node v6.0.0+, you can use `crypto.timingSafeEqual()` to safely
        // compare two values.
        && ctx.username === 'ankit'
        && ctx.password === 'shruti')
      ctx.accept();
    else
      ctx.reject();
  }).on('ready', function() {
    console.log('Client authenticated!');
  });

  client.on('session',function(accept,reject)
  {
      console.log("Client asking for session");
      var session = accept();
      var handleCount = 0;
      var names=[]

      session.on('sftp',function(accept,reject)
      {
          console.log('Client sftp connection')
          var sftpStream = accept();

          sftpStream.on('OPENDIR',function(reqID,path)
          {
            var handle = new Buffer(4);
            handle.writeUInt32BE(handleCount++, 0, true);
            sftpStream.handle(reqID,handle);
            console.log(handle);
            console.log('Opening Read Directory for  --'+path);
            console.log(reqID);
            console.log(path);  

          }).on('READDIR',function(reqID,handle)
          {
           console.log('Read request')
           console.log(reqID);
            if(handle.length!==4)
            return sftpStream.status(reqID, STATUS_CODE.FAILURE,'There was failure')
            
                sftpStream.status(reqID, STATUS_CODE.OK,'Everything ok')
                sftpStream.name(reqID,names);     
              
              
          })
          


      })


  })

  






}).listen(0, '127.0.0.1', function() {
  console.log('Listening on port ' + this.address().port);
});

srv.listen(22)

Upvotes: 1

Views: 3290

Answers (1)

Stevan Goode
Stevan Goode

Reputation: 41

The client will send multiple READDIR requests. On the first request, you should send the file listing, on the second you should send an EOF status, to tell the client the listing has finished.

An example would be:

let listSent = false;
let names = [];

sftpStream.on('OPENDIR', function (reqID, path) {
    listSent = false;
    sftpStream.handle(new Buffer());
});

sftpStream.on('READDIR', function (reqID, handle) {
    if (listSent) {
        sftpStream.status(reqID, STATUS_CODE.EOF);
        return;
    }

    sftpStream.name(reqID, names);
    listSent = true;
});

Upvotes: 4

Related Questions