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 :
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.
<?php
class Transfert_sftp
{
/**
* Information de connection
* @var resource
*/
private $_connection;
/**
* Information de flux
* @var resource
*/
private $_stream;
public function __construct($host, $port, $login, $password)
{
$this->_connection = ssh2_connect($host, $port);
if (!$this->_connection) {
// Logguer une erreur de connexion
throw newException('Erreur de connexion');
}
if (! ssh2_auth_password($this->_connection, $login, $password)) {
throw new Exception('Erreur d\'authentification avec '.$login .' et ' . $password);
}
$this->_stream = ssh2_sftp($this->_connection);
if (! $this->_stream) {
throw new Exception('Impossible d\'initialiser la connection SFTP');
}
}
/**
*
* @param $remoteDir
* @param $localDir
* @param $params
* @return unknown_type
*/
public function getDir ($remoteDir, $localDir)
{
$streamDir = 'ssh2.sftp://'.$this->_stream.$remoteDir;
if ($handle === false) {
throw new Exception('Impossible de se placer sur le répertoire '.$remoteDir);
}
while (false !==
($file =
readdir($handle))) {
if ($this->_allowedFile($file, $params)) {
$this->getFile($remoteDir, $file, $localDir);
}
}
}
/**
*
* @param $localDir
* @param $remoteDir
* @return unknown_type
*/
public function putDir ($localDir, $remoteDir)
{
while (false !==
($file =
readdir($handle))) {
if ($this->_allowedFile($file)) {
$this->putFile($localDir, $file, $remoteDir, $params);
}
}
}
/**
*
* @param $remoteDir
* @param $remoteFile
* @param $localDir
*/
public function getFile ($remoteDir, $nameFile, $localDir)
{
$streamFile = 'ssh2.sftp://'.$this->_stream.$remoteDir.'/'.$nameFile;
$localFile = $localDir.'/'.$nameFile;
if ($contents === false) {
throw new Exception('Impossible de récupérer '.$remoteFile);
}
$return = file_put_contents($localFile, $contents);
if ($return === false) {
throw new Exception('Impossible de d\'écrire '.$localFile);
}
} else {
throw new Exception('Fichier '.$remoteFile.' inexistant');
}
}
/**
*
* @param $localDir
* @param $localFile
* @param $remoteDir
*/
public function putFile ($localDir, $nameFile, $remoteDir)
{
$streamFile = 'ssh2.sftp://'.$this->_stream.$remoteDir.'/'.$nameFile;
$localFile = $localDir.'/'.$localFile;
if ($contents === false) {
throw new Exception('Impossible d\'envoyer '.$nameFile);
}
$return = file_put_contents($streamFile, $contents);
if ($return === false) {
throw new Exception('Impossible de d\'écrire '.$streamFile);
}
} else {
throw new Exception('Fichier '.$localFile.' inexistant');
}
}
/**
*
* @param $file
* @param $params
* @return boolean
*/
private function _allowedFile ($file, $params)
{
return false;
}
return true;
}
}
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é.