94

I have came across many PHP scripts for web FTP clients. I need to implement a SFTP client as a web application in PHP. Does PHP support for SFTP? I couldn't find any samples. Can anyone help me with this?

Ranganathan
  • 103
  • 7
indranama
  • 1,183
  • 2
  • 9
  • 6

6 Answers6

79

PHP has ssh2 stream wrappers (disabled by default), so you can use sftp connections with any function that supports stream wrappers by using ssh2.sftp:// for protocol, e.g.

file_get_contents('ssh2.sftp://user:pass@example.com:22/path/to/filename');

or - when also using the ssh2 extension

$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');

See http://php.net/manual/en/wrappers.ssh2.php

On a side note, there is also quite a bunch of questions about this topic already:

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • file_get_contents and file_put_contents both work awesome. never knew they worked with sftp and it's so much easier than using the built in sftp stuff. Thanks! – jbrahy Mar 11 '15 at 22:53
  • 5
    Even when using file_get_contents() you still need the ssh2 extension (afaik). – StanE Jan 26 '16 at 05:28
  • debian/ubuntu packages : apt install libssh2-1-dev php-ssh2 – Ajay Singh Jan 21 '20 at 02:44
  • This answer doesn't seem correct. SFTP uses an encrypted private key to provide its security, so it requires the pathname of a private key and its passphrase in any PHP solution. The answer does not provide this functionality. I don't know why it got so many upvotes. – David Spector Jan 20 '21 at 12:52
  • 1
    @DavidSpector that depends only on settings of server. You can have regular USER/PASS combination even with SFTP/SSH. – Lukáš Klíma May 02 '22 at 11:47
  • I think you mean that you can have a password in addition to using SFTP. True. – David Spector May 03 '22 at 12:17
45

The ssh2 functions aren't very good. Hard to use and harder yet to install, using them will guarantee that your code has zero portability. My recommendation would be to use phpseclib, a pure PHP SFTP implementation.

Yahel
  • 37,023
  • 22
  • 103
  • 153
calgaryhit
  • 479
  • 3
  • 2
32

I found that "phpseclib" should help you with this (SFTP and many more features). http://phpseclib.sourceforge.net/

To Put the file to the server, simply call (Code example from http://phpseclib.sourceforge.net/sftp/examples.html#put)

<?php
include('Net/SFTP.php');

$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

// puts a three-byte file named filename.remote on the SFTP server
$sftp->put('filename.remote', 'xxx');
// puts an x-byte file named filename.remote on the SFTP server,
// where x is the size of filename.local
$sftp->put('filename.remote', 'filename.local', NET_SFTP_LOCAL_FILE);
Prut Udomwattawee
  • 665
  • 1
  • 9
  • 13
5

Install Flysystem v1:

composer require league/flysystem-sftp

Then:

use League\Flysystem\Filesystem;
use League\Flysystem\Sftp\SftpAdapter;

$filesystem = new Filesystem(new SftpAdapter([
    'host' => 'example.com',
    'port' => 22,
    'username' => 'username',
    'password' => 'password',
    'privateKey' => 'path/to/or/contents/of/privatekey',
    'root' => '/path/to/root',
    'timeout' => 10,
]));
$filesystem->listFiles($path); // get file lists
$filesystem->read($path_to_file); // grab file
$filesystem->put($path); // upload file
....

Read:

https://flysystem.thephpleague.com/v1/docs/

Upgrade to v2:

https://flysystem.thephpleague.com/v2/docs/advanced/upgrade-to-2.0.0/

Install

 composer require league/flysystem-sftp:^2.0

Then:

//$filesystem->listFiles($path); // get file lists
$allFiles = $filesystem->listContents($path)
->filter(fn (StorageAttributes $attributes) => $attributes->isFile());

$filesystem->read($path_to_file); // grab file
//$filesystem->put($path); // upload file
$filesystem->write($path);
Salines
  • 5,674
  • 3
  • 25
  • 50
0

After messing around with PECL ssh2 I decided to take a look at phpseclib 3 and it worked out of the box. No installation on the server. I used composer to install it and put the code in. It has a ton of useful things and it's free. These are the steps:

  1. Run this composer install on your PHP app folder. I used VS Code and I opened a terminal window (need Composer to be installed on your machine first):

    composer require phpseclib/phpseclib:~3.0

  2. Use the basic example from here: https://phpseclib.com/docs/sftp

    use phpseclib3\Net\SFTP;

    $sftp = new SFTP('localhost');

    $sftp->login('username', 'password');

    $sftp->put('filename.remote', 'filename.local', SFTP::SOURCE_LOCAL_FILE);

Other useful links: GitHub: https://github.com/phpseclib/phpseclib and website: https://phpseclib.com/

Adrian P.
  • 5,060
  • 2
  • 46
  • 47
-1

I performed a full-on cop-out and wrote a class which creates a batch file and then calls sftp via a system call. Not the nicest (or fastest) way of doing it but it works for what I need and it didn't require any installation of extra libraries or extensions in PHP.

Could be the way to go if you don't want to use the ssh2 extensions

DaveyBoy
  • 2,928
  • 2
  • 17
  • 27
  • related thread that helped me: https://groups.google.com/forum/#!topic/comp.security.ssh/_55TdDdUTCw – Quamis Feb 24 '15 at 17:23