peLmeL.org
Accueil du site > peLmeL Blog > Bouts de code > Class SSH2/SFTP en PHP

Class SSH2/SFTP en PHP

lundi 7 septembre 2009, par Brice Favre


Dans le cadre d’un projet, j’ai eu la charge de la réalisation d’un gestionnaire automatique de transfert SFTP. Le langage étant libre, j’ai choisi de le réaliser en PHP. Pour ce faire, j’ai tout d’abord du procéder à l’installation de la librairie SSH2 pour PHP puis développer une classe.

Installation des librairies

Pour pouvoir utiliser SFTP (à ne pas confondre avec FTPS), il convient d’ajouter une librairie supplémentaire. Sous Windows, pas de soucis, ça a déjà été compilé pour vous. Il vous suffira de télécharger la dll de la placer dans les répertoires de vos librairies, puis de déclarer php_ssh2.dll dans php.ini.

Du coté de Linux, vous pouvez utiliser la commande pecl pour compiler la librairie :

  1. pecl install ssh2

A noter qu’il est possible de se passer de pecl en téléchargeant l’archive et la compilant. Quelque soit la méthode, il faudra ensuite de déplacer la librairie ssh2.so dans le répertoire des librairies et ensuites de modifier le fichier php.ini.

Attention à ce que votre système contienne la librairie SSH2.

Classe de transfert SFTP

Pour la classe de transfert, j’ai pris le partir de construira la connexion dès l’instanciation de l’objet. Les méthodes de la classe permettent de récupérer un répertoire entier ou bien un fichier individuel et envoyer une série de fichier, ainsi qu’un fichier individuel.

  1. <?php
  2.  
  3. class Transfert_sftp
  4. {
  5.  
  6.   /**
  7.    * Information de connection
  8.    * @var resource
  9.    */
  10.   private $_connection;
  11.  
  12.   /**
  13.    * Information de flux
  14.    * @var resource
  15.    */
  16.   private $_stream;
  17.  
  18.   public function __construct($host, $port, $login, $password)
  19.   {
  20.     $this->_connection = ssh2_connect($host, $port);
  21.     if (!$this->_connection) {
  22.       // Logguer une erreur de connexion
  23.       throw newException('Erreur de connexion');
  24.     }
  25.     if (! ssh2_auth_password($this->_connection, $login, $password)) {
  26.       throw new Exception('Erreur d\'authentification avec '.$login .' et ' . $password);
  27.     }
  28.  
  29.     $this->_stream = ssh2_sftp($this->_connection);
  30.  
  31.     if (! $this->_stream) {
  32.       throw new Exception('Impossible d\'initialiser la connection SFTP');
  33.     }
  34.   }
  35.  
  36.   /**
  37.    *
  38.    * @param $remoteDir
  39.    * @param $localDir
  40.    * @param $params
  41.    * @return unknown_type
  42.    */
  43.   public function getDir ($remoteDir, $localDir)
  44.   {
  45.     $streamDir = 'ssh2.sftp://'.$this->_stream.$remoteDir;
  46.     $handle = opendir($streamDir);
  47.     if ($handle === false) {
  48.       throw new Exception('Impossible de se placer sur le répertoire '.$remoteDir);
  49.     }
  50.     while (false !== ($file = readdir($handle))) {
  51.       if ($this->_allowedFile($file, $params)) {
  52.         $this->getFile($remoteDir, $file, $localDir);
  53.       }
  54.     }
  55.   }
  56.  
  57.   /**
  58.    *
  59.    * @param $localDir
  60.    * @param $remoteDir
  61.    * @return unknown_type
  62.    */
  63.   public function putDir ($localDir, $remoteDir)
  64.   {
  65.     $handle = opendir($localDir);
  66.       while (false !== ($file = readdir($handle))) {
  67.         if ($this->_allowedFile($file)) {
  68.           $this->putFile($localDir, $file, $remoteDir, $params);
  69.         }
  70.     }
  71.   }
  72.  
  73.   /**
  74.    *
  75.    * @param $remoteDir
  76.    * @param $remoteFile
  77.    * @param $localDir
  78.    */
  79.     public function getFile ($remoteDir, $nameFile, $localDir)
  80.     {
  81.  
  82.         $streamFile = 'ssh2.sftp://'.$this->_stream.$remoteDir.'/'.$nameFile;
  83.        
  84.         $localFile = $localDir.'/'.$nameFile;
  85.         if (file_exists($streamFile)) {
  86.             $contents = file_get_contents($streamFile);
  87.             if ($contents === false) {
  88.                 throw new Exception('Impossible de récupérer '.$remoteFile);
  89.             }
  90.             $return = file_put_contents($localFile, $contents);
  91.             if ($return === false) {
  92.                 throw new Exception('Impossible de d\'écrire '.$localFile);
  93.             }
  94.         } else {
  95.             throw new Exception('Fichier '.$remoteFile.' inexistant');
  96.         }
  97.     }
  98.  
  99.     /**
  100.      *
  101.      * @param $localDir
  102.      * @param $localFile
  103.      * @param $remoteDir
  104.      */
  105.     public function putFile ($localDir, $nameFile, $remoteDir)
  106.     {
  107.         $streamFile = 'ssh2.sftp://'.$this->_stream.$remoteDir.'/'.$nameFile;
  108.        
  109.         $localFile = $localDir.'/'.$localFile;
  110.         if (file_exists($localFile)) {
  111.             $contents = file_get_contents($localFile);
  112.             if ($contents === false) {
  113.                 throw new Exception('Impossible d\'envoyer '.$nameFile);
  114.             }
  115.             $return = file_put_contents($streamFile, $contents);
  116.             if ($return === false) {
  117.                 throw new Exception('Impossible de d\'écrire '.$streamFile);
  118.             }
  119.         } else {
  120.             throw new Exception('Fichier '.$localFile.' inexistant');
  121.         }
  122.     }
  123.  
  124.     /**
  125.      *
  126.      * @param $file
  127.      * @param $params
  128.      * @return boolean
  129.      */
  130.     private function _allowedFile ($file, $params)
  131.     {
  132.         if (is_dir($file) || substr("$file", 0, 1) == "." ) {
  133.             return false;
  134.         }
  135.         return true;
  136.     }
  137. }

La classe est perfectible, n’hésitez pas à me faire vos remarques, vos retours pour améliorer . Pour ma part je l’ai insérer dans un ensemble plus grand avec une factory pour gérer également les connections FTP. Je l’ai également intégrer dans Zend Framework avec une très grande facilité.

Répondre à cet article

3 Messages de forum


Suivre la vie du site RSS 2.0 | Plan du site | Espace privé | SPIP | squelette