I was looking for a nice way of uploading a local file to a remote SFTP server with PHP today. I came across the ssh2
set of functions (e.g. http://php.net/ssh2_connect) which seem to fit the bill, but unfortunately the PECL package wasn’t PHP7-compatible.
An alternative was to use Curl. After a bit of messing around, I managed to get a working solution together which is summarised here:
$dataFile = '/path/to/file'; $sftpServer = 'sftp.foo.com'; $sftpUsername = 'user'; $sftpPassword = 'pass'; $sftpPort = 22; $sftpRemoteDir = '/files'; $ch = curl_init('sftp://' . $sftpServer . ':' . $sftpPort . $sftpRemoteDir . '/' . basename($dataFile)); $fh = fopen($dataFile, 'r'); if ($fh) { curl_setopt($ch, CURLOPT_USERPWD, $sftpUsername . ':' . $sftpPassword); curl_setopt($ch, CURLOPT_UPLOAD, true); curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_SFTP); curl_setopt($ch, CURLOPT_INFILE, $fh); curl_setopt($ch, CURLOPT_INFILESIZE, filesize($dataFile)); curl_setopt($ch, CURLOPT_VERBOSE, true); $verbose = fopen('php://temp', 'w+'); curl_setopt($ch, CURLOPT_STDERR, $verbose); $response = curl_exec($ch); $error = curl_error($ch); curl_close($ch); if ($response) { echo "Success"; } else { echo "Failure"; rewind($verbose); $verboseLog = stream_get_contents($verbose); echo "Verbose information:\n" . $verboseLog . "\n"; } }
Note the use of the CURLOPT_VERBOSE
option which can be handy for debugging failed connections.
Looking for reliable PHP hosting?. I can thoroughly recommend Linode.
what version of curl libcurl are you using I get no sftp support from the libcurl thanks Tom
Thanks you for help, good worked….. i am used match method for connect Sftp, but i have a problem: can you help me?
FailureVerbose information: * Initialized password authentication * Authentication complete * Upload failed: No such file or directory (2/-31) * Connection #4 to host sftp.xxxxxxx.com left intact
I have had such errors in the past. Caused by either permission issues or not understanding where SFTP is actually uploading to. Try uploading to just the ‘root’ path ‘/’ and see where the file ends up.
Perfect!
I hunted high and low for SFTP uploads from PHP and all were problematic – requiring external packages.
This worked first time!
Many thanks
worked fine, its gr8. thanks man.
This worked Great! I searched for 2 days for a solution for SFTP file transfer and tried atleast 10 different options. This worked right out of the box. You sir are a genius!
Great work Glen, especially the use of the CURLOPT_VERBOSE option!
I get
SSH public key authentication failed: Unable to extract public key from private key file: Unable to open private key file
This worked out of the box, no hassle,,no configuration headaches.
Many thanks!
hi, the script works for a short period of time. Its supposed to download a 1.9MB file and its only 16kb when put to the server.
Hosting support says this is the error:
RELINQUISH PRIVS: unable to seteuid(PR_ROOT_UID): Operation not permitted
say the script is trying to change folder / file permissions which is not allowed.
any clue? thanks.
Hi Glenn
Great script.
Is there a way to take a look and see if the uploaded file exists on the remote server?
I have read that there is no function to do that in curl
Hello ,I used this script under windows 2016 / Apache 2.4.38 (Win64) OpenSSL/1.1.1a
php 7.3.6 with curl 7.64.0 and libssh2/1.8.2 I have the following error. I’m trying for a couple of hours and getting crasy …. Thanks for any help * Connected to cloudftp.xxxxxx.com (yy.yy.yy.yyy) port 22 (#0)
* SSH MD5 fingerprint: xx1x1x11x1x11xx11x1x1x1x1x1
* SSH authentication methods available: password,publickey
* Using SSH private key file ”
* SSH public key authentication failed: Unable to extract public key from private key file: Unable to open private key file
* Initialized password authentication
* Authentication complete
* Upload failed: Operation failed (4/-31)
* Connection #0 to host cloudftp.xxxxxx.com left intact
Good morning,
Thank you, the solution worked like a charm!
How does one confirm the file integrity i.e. the file got uploaded to remote server?
How do you check the file size on remote server after its uploaded using curl?
Thanks,
Roma
its very rare to find a sample blob of code which works first time !
thank you
incase it helps anyone else : I’m on PHP 8 on IIS