2017-03-15 1 views
0

Je crée donc une classe et souhaite créer une méthode qui prend un fichier sur un serveur SFTP et produit un flux de lecture qui peut être redirigé vers d'autres flux/fonctions. Je suis la plupart du temps là-bas, sauf que mon readStream agit bizarrement. Voici le code correspondant:Noeud Async ReadStream de la connexion SFTP

const Client = require('ssh2').Client, 
     Readable = require('stream').Readable, 
     async = require('async'); 

/** 
* Class Definition stuff 
* ...... 
*/ 

getStream(get) { 
    const self = this; 
    const rs = new Readable; 
    rs._read = function() { 
     const read = this; 
     self.conn.on('ready', function(){ 
      self.conn.sftp(function(err,sftp) { 
       if(err) return err; 

       sftp.open(get, 'r', function(err, fd){ 
        sftp.fstat(fd, function(err, stats) { 

         let bufferSize = stats.size, 
          chunkSize = 512,//bytes 
          buffer = new Buffer(bufferSize), 
          bytesRead = 0; 

         async.whilst(
          function() { 
           return bytesRead < bufferSize; 
          }, 
          function (done) { 
           sftp.read(fd, buffer, bytesRead, chunkSize, bytesRead, 
           function (err, bytes, buff) { 
            if (err) return done(err); 
            // console.log(buff.toString('utf8')); 
            read.push(buff); 
            bytesRead += bytes; 
            done(); 
           }); 
          }, 
          function (err) { 
           if (err) console.log(err); 
           read.push(null); 
           sftp.close(fd); 
          } 
         ); 

        }); 
       }); 
      }); 
     }).connect(self.connectionObj); 
    } 
    return rs; 

} 

Ailleurs, je qualifierais cette méthode comme ceci:

let sftp = new SFTP(credentials); 

sftp.getStream('/path/file.csv') 
.pipe(toStuff); 
.pipe(toOutput); 

Alors, histoire courte. Au cours de l'opération SFTP.read read.push(buff) continue à pousser la même première partie du fichier encore et encore. Cependant, quand je console.log(buff) il flux correctement le fichier complet?

Alors je me gratte la tête en me demandant ce que je fais de mal avec le flux de lecture que c'est seulement pousser le début du fichier et ne pas continuer à la partie suivante du tampon.

est ici la documentation sur le client SSH2 SFTP: https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md

J'ai utilisé cette question SO comme source d'inspiration pour ce que je l'ai écrit ci-dessus: node.js fs.read() example

Ceci est similaire/lié: Reading file from SFTP server using Node.js and SSH2

Répondre

0

Ok, après une beaucoup d'ennuis, j'ai réalisé que je faisais quelques erreurs. Tout d'abord, la fonction _read est appelée chaque fois que le flux est prêt à lire plus de données, ce qui signifie que la connexion SFTP a été démarrée à chaque fois que _read a été appelée. Cela signifiait également que la fonction sftp.read() commençait à chaque fois, ce qui revenait au point de départ.

J'avais besoin d'un moyen pour d'abord configurer la connexion, puis lire et diffuser les données du fichier, donc j'ai choisi la bibliothèque noms. Voici le code final si quelqu'un est intéressé:

getStream (get) { 
    const self = this; 

    let connection, 
     fileData, 
     buffer, 
     totalBytes = 0, 
     bytesRead = 0; 

    return nom(
     // _read function 
     function(size, next) { 
      const read = this; 

      // Check if we're done reading 
      if(bytesRead === totalBytes) { 
       connection.close(fileData); 
       connection.end(); 
       self.conn.end(); 
       console.log('done'); 
       return read.push(null); 
      } 

      // Make sure we read the last bit of the file 
      if ((bytesRead + size) > totalBytes) { 
       size = (totalBytes - bytesRead); 
      } 

      // Read each chunk of the file 
      connection.read(fileData, buffer, bytesRead, size, bytesRead, 
       function (err, byteCount, buff, pos) { 
        // console.log(buff.toString('utf8')); 
        // console.log('reading'); 
        bytesRead += byteCount; 
        read.push(buff); 
        next(); 
       } 
      ); 
     }, 
     // Before Function 
     function(start) { 
      // setup the connection BEFORE we start _read 
      self.conn.on('ready', function(){ 
       self.conn.sftp(function(err,sftp) { 
        if(err) return err; 
        sftp.open(get, 'r', function(err, fd){ 
         sftp.fstat(fd, function(err, stats) { 
          connection = sftp; 
          fileData = fd; 
          totalBytes = stats.size; 
          buffer = new Buffer(totalBytes); 
          console.log('made connection'); 
          start(); 
         }); 
        }); 
       }); 
      }).connect(self.connectionObj); 
     }) 
} 

Toujours à la recherche de commentaires. Cela ne fonctionne pas aussi vite que je l'espère, alors laissez-moi savoir si vous avez des idées pour accélérer le flux.