Unlike FTP, SFTP is the only file transfer protocol that provides protection against attacks in the data transfer process, making it the best protocol for file transfer operations. PHP offers the ssh2 functions, that you can use to access a SFTP server, however these methods are unreliable and difficult to handle (to say nothing of the installation) and will generate code of 0 portability. In this case, to connect to a SFTP server in PHP we are going to use the phpseclib.
In this article, you'll learn how to connect to a SFTP server using phpseclib in a Symfony 3 project.
Requirements
In order to connect to a SFTP server in PHP, we are going to use the phpseclib library. Phpseclib is a MIT-licensed pure-PHP implementations of an arbitrary-precision integer arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael, AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
The preferred way of installation is with composer, execute the following command on your command prompt:
composer require phpseclib/phpseclib
Alternatively, you can modify your composer.json file and add the library as a dependency manually and then execute composer install
:
{
"require": {
"phpseclib/phpseclib": "^2.0"
}
}
And you are ready to use phpseclib.
Login to SFTP server
The following snippet shows how to login to a SFTP server easily in a controller:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
// Include the SFTP component of phpseclib
use phpseclib\Net\SFTP;
class DefaultController extends Controller
{
public function indexAction()
{
$sftp = new SFTP('myserver.sftpdirection.com');
if (!$sftp->login('username', 'password')) {
throw new \Exception('Cannot login into your server !');
}
// And you'll be able to use the SFTP tool as you wish !
// $sftp->DO_SOMETHING
return $this->render('index.html.twig', [
]);
}
}
The $sftp
variable will allow you to use all the methods available for the SFTP connection, creation of folders, list a directory, download or upload etc.
Directory management
The directory managements consists of the basic commands and task that you need to interact with a directory, folder or files. In the most known tasks of directory management you'll find:
- Creation of a directory (
mkdir
). - Navigation between directories (
chdir
). - The elimination of a directory (
rmdir
anddelete
for recursive).
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
// Include the SFTP component of phpseclib
use phpseclib\Net\SFTP;
class DefaultController extends Controller
{
public function indexAction()
{
$sftp = new SFTP('myserver.sftpdirection.com');
if (!$sftp->login('username', 'password')) {
throw new \Exception('Cannot login into your server !');
}
$sftp->mkdir('test'); // create directory 'test'
$sftp->chdir('test'); // open directory 'test'
echo $sftp->pwd(); // show that we're in the 'test' directory
$sftp->chdir('..'); // go back to the parent directory
$sftp->chdir('/var/www/vhosts/myfolder'); // navigate to myfolder
/// DANGEROUS ZONE, THINK WHAT YOU DO BEFORE UNCOMMENT
// $sftp->rmdir('test'); // delete the directory
// if the directory had files in it we'd need to do a recursive delete
// $sftp->delete('test', true);
return $this->render('index.html.twig', [
]);
}
}
Directory listing
To list a directory, you only need to know the path. Then use the chdir command and finally obtain the content of the current directory using either nlist
or rawlist
:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use phpseclib\Net\SFTP;
class DefaultController extends Controller
{
public function indexAction()
{
$sftp = new SFTP('myserver.sftpdirection.com');
if (!$sftp->login('username', 'password')) {
throw new \Exception('Cannot login into your server !');
}
$sftp->chdir('/var/www/vhosts/ourcodeworld.com'); // open directory 'ourcodeworld.com'
// Send a variable named data into the twig view to be dumped
return $this->render('index.html.twig', [
'data' => [
'list' => $sftp->nlist(), // == $sftp->nlist('.')
'raw_list' => $sftp->rawlist() // == $sftp->rawlist('.')
]
]);
}
}
In this case, we've just navigated to the ourcodeworld.com folder and we'll list the content of the folder using the previously mentioned commands. In our twig view (index.html.twig
), we used the {{dump(data)}}
function to display the content of the folder, and the output should be similar to:
The list
item contains and array of strings with only the names of the files and folders. The raw_list
item will contain an array with the name of the folder or file as index and as content, there will be more sensitive information as date of creation, permissions, size etc.
Note that you can get the specific information about a folder or file without list all the content of a directory using the size, stat and lstat methods i.e:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use phpseclib\Net\SFTP;
class DefaultController extends Controller
{
public function indexAction()
{
$sftp = new SFTP('myserver.sftpdirection.com');
if (!$sftp->login('username', 'password')) {
throw new \Exception('Cannot login into your server !');
}
$directory = '/var/www/vhosts/ourcodeworld.com';
return $this->render('sandboxBundle:Default:index.html.twig', [
'data' => [
'size' => $sftp->size($directory),
'stat' => $sftp->stat($directory),
'lstat' => $sftp->lstat($directory)
]
]);
}
}
stat
and lstat
return associative arrays with misc information about the files. lstat
and stat
are identical with the caveat that when the file in question is a symbolic link the information returned refers to the link itself and not the file (or directory) being linked to. size
returns the 'size' index of the associative array returned by lstat
.
Download a file
You can either download a file to save it in a local path or retrieve the content (as text) of the file using the get
method.
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use phpseclib\Net\SFTP;
class DefaultController extends Controller
{
public function indexAction()
{
$sftp = new SFTP('myserver.sftpdirection.com');
if (!$sftp->login('username', 'password')) {
throw new \Exception('Cannot login into your server !');
}
$filepath = '/www/vhosts/ourcodeworld.com/myfile.txt';
// the get method returns the content of a remote file
$filecontent = $sftp->get($filepath);
// Alternatively, instead of retrieve the content, download the file
// copy the file into a local directory providing the local path as second parameter
$sftp->get($filepath, '/myPC/folder/myfile.txt');
return $this->render('index.html.twig', [
'filecontent' => $filecontent
]);
}
}
Upload a file
To upload a file into a remote server, use the put method. This method expects as first argument the remote path where the file will be uploaded and as second parameter the path of the file that will be uploaded.
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use phpseclib\Net\SFTP;
class DefaultController extends Controller
{
public function indexAction()
{
$sftp = new SFTP('myserver.sftpdirection.com');
if (!$sftp->login('username', 'mypassword')) {
throw new \Exception('Cannot login into your server !');
}
$remoteFile = '/var/www/vhosts/myfile.txt';
$localFile = '/my-local-server/mydownloadedfile.txt';
// Upload of the local path (second argument)
// into the remote path (first argument)
$sftp->put($remoteFile, $localFile);
return $this->render('index.html.twig', [
]);
}
}
Delete and rename a file
To delete folder and files use the delete method. If you want to rename a file use the rename method.
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use phpseclib\Net\SFTP;
class DefaultController extends Controller
{
public function indexAction()
{
$sftp = new SFTP('myserver.sftpdirection.com');
if (!$sftp->login('username', 'password')) {
throw new \Exception('Cannot login into your server !');
}
$filepath = '/www/vhosts/ourcodeworld.com/myfile.txt';
$folderpath = '/www/vhosts/ourcodeworld.com'
$sftp->delete($filepath); // doesn't delete directories
// recursive delete
$sftp->delete($folderpath, true); // deletes a directory and all its contents
//rename filename1 for mynewname
$sftp->rename('filename1.txt', 'mynewname.txt');
return $this->render('index.html.twig', [
]);
}
}
Have fun !