How to download a file from SFTP using PHP? - php

I am trying to download a file from an sftp server using php but I can't find any correct documentation to download a file.
<?php
$strServer = "pass.com";
$strServerPort = "22";
$strServerUsername = "admin";
$strServerPassword = "password";
$resConnection = ssh2_connect($strServer, $strServerPort);
if(ssh2_auth_password($resConnection, $strServerUsername, $strServerPassword)) {
$resSFTP = ssh2_sftp($resConnection);
echo "success";
}
?>
Once I have the SFTP connection open, what do I need to do to download a file?

Using phpseclib, a pure PHP SFTP implementation:
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
exit('Login Failed');
}
// outputs the contents of filename.remote to the screen
echo $sftp->get('filename.remote');
?>

Once you have your SFTP connection open, you can read files and write using standard PHP functions such as fopen, fread, and fwrite. You just need to use the ssh2.sftp:// resource handler to open your remote file.
Here is an example that will scan a directory and download all files in the root folder:
// Assuming the SSH connection is already established:
$resSFTP = ssh2_sftp($resConnection);
$dirhandle = opendir("ssh2.sftp://$resSFTP/");
while ($entry = readdir($dirhandle)){
$remotehandle = fopen("ssh2.sftp://$resSFTP/$entry", 'r');
$localhandle = fopen("/tmp/$entry", 'w');
while( $chunk = fread($remotehandle, 8192)) {
fwrite($localhandle, $chunk);
}
fclose($remotehandle);
fclose($localhandle);
}

Related

How to read csv file from zip file on remote server with php?

I would like to read a zip file from a remote server. I currently have to following code :
private $sftp;
public function __construct($username, $password, $serverName)
{
$this->sftp = new Net_SFTP($serverName);
if (!$this->sftp->login($username, $password)) {
exit('Login Failed');
}
}
public function buildRecords() {
$sftp = $this->sftp;
$sftp -> chdir(Constants::QUICKCHECK_OUTPUT_DIRECTORY);
echo $sftp->pwd(); // show that we're in the 'test' directory
// print_r($sftp->nlist());
foreach($sftp->nlist() as $zipFile) {
$handle = fopen("zip://" . $zipFile,'r');
while($line = fgetcsv($handle)) {
print_r($line);
}
}
}
When I run this code and call these methods I get the error
Warning: fopen(zip://test.zip): failed to open stream: operation failed in /var/www/html/update_alerts2.php on line 67
How do I fix this error? (I'm using the phpseclib to sftp)
fopen will not magically be able to access files on a remote server only because you have logged into the server using phpseclib before.
You have to use phpseclib functions to retrieve the file contents.
Unfortunately phpseclib does not offer a way to read remote file contents by lines/chunks. But as it is CSV file, it is probably OK to load from file to memory at once. For that you can use SFTP::get, if you do not specify the $local_file argument:
$contents = $sftp->get($zipFile);
$lines = explode("\n", $contents);
foreach ($lines as $line)
{
if (strlen($line) > 0)
{
$fields = str_getcsv($line);
print_r($fields);
}
}

PHP FTP Get the status when copying large files [duplicate]

I have a working FTP file download script.
The files I am downloading will be about 2-4 GB per day.
I was wondering if there was a way to get the percent of the file where it's at?
I have looked on php.net and on here but I couldn't find any similar questions and rather spend more time looking I figure I would ask people much smarter than myself.
I was thinking about if there was a function to see where it's at in the download, but I couldn't find one since ftp_get would have to complete first so that eliminated the chance of flushing the buffer every few seconds to display a new percent.
Anyone?
Here is my code: I hid all of my variables above it.
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) {
echo "Successfully written to $local_file\n";
} else {
echo "There was a problem\n";
}
ftp_close($conn_id);
EDIT:
I added ftp_nb_get and here is my code for that. It keeps downloading fine, just doesn't echo it out to the browser.
$ret = ftp_nb_get($conn_id, $local_file, $server_file, FTP_BINARY, $size);
while ($ret == FTP_MOREDATA) {
echo round((filesize($local_file)/$server_size)*100)."%\n";
$ret = ftp_nb_continue($conn_id);
}
Try using the non-blocking version ftp_nb_get() and ftp_nb_continue() in a loop, and check for the saved file's size.
It can be implemented easily using FTP URL protocol wrappers:
$url = "ftp://username:password#ftp.example.com/remote/source/path/file.zip";
$size = filesize($url) or die("Cannot retrieve size file");
$hin = fopen($url, "rb") or die("Cannot open source file");
$hout = fopen("/local/dest/path/file.zip", "wb") or die("Cannot open destination file");
while (!feof($hin))
{
$buf = fread($hin, 10240);
fwrite($hout, $buf);
echo "\r".intval(ftell($hout)/$size*100)."%";
}
echo "\n";
fclose($hout);
fclose($hin);
Regarding your attempts using ftp_nb_get:
The filesize caches the results, so calling it repeatedly will get you the same value. You have to call clearstatcache.
A full code is like:
$conn_id = ftp_connect("ftp.example.com");
ftp_login($conn_id, "username", "password");
ftp_pasv($conn_id, true);
$local_path = "/local/dest/path/file.zip";
$remote_path = "/remote/source/path/file.zip";
$size = ftp_size($conn_id, $remote_path);
$ret = ftp_nb_get($conn_id, $local_path, $remote_path, FTP_BINARY);
while ($ret == FTP_MOREDATA)
{
clearstatcache(false, $local_path);
echo "\r".intval(filesize($local_path)/$size*100)."%";
$ret = ftp_nb_continue($conn_id);
}
echo "\n";
Alternatively use ftp_nb_fget and query the file handle, like my first example.
You should try buffer flush - ob_flush() and flush().
This technique works, I already used it.
here is a tutorial
I am sure that you can wind yourself some more.
Just google "progress php flush buffer"

PHP copy file from HTTP URL to FTP server

I have this link: http://gdlp01.c-wss.com/gds/6/0300002536/03/PSG11_CUG_EN_03.pdf and I want to copy this file to my FTP server. I tried:
$file = "http://gdlp01.c-wss.com/gds/6/0300002536/03/PSG11_CUG_EN_03.pdf";
$data = file_get_contents($url);
$ftp_server = "ftp_server";
$ftp_user = "ftp_user";
$ftp_pass = "ftp_pass";
$ftp = ftp_connect($ftp_server,21) or die("Couldn't connect to $ftp_server");
if (ftp_login($ftp, $ftp_user, $ftp_pass)) {
echo "Connecté en tant que $ftp_user#$ftp_server\n";
} else {
echo "Connexion impossible en tant que $ftp_user\n";
}
The connection was successful, but after that I do not know how to start.
You'll have to use ftp_fput, but I'm not sure if this function is able to handle an URL (I don't think so), so I decided to put your existing variable into the memory and to fake a file handler:
$tmpFile = fopen('php://memory', 'r+');
fputs($tmpFile, $data);
rewind($tmpFile);
if (ftp_fput($ftp, 'manual.pdf', $tmpFile, FTP_ASCII)) {
echo "worked";
} else {
echo "did not work";
}
If you have URL wrappers enabled, it's as easy as:
$file = "http://gdlp01.c-wss.com/gds/6/0300002536/03/PSG11_CUG_EN_03.pdf";
$ftp_server = "ftp_server";
$ftp_user = "ftp_user";
$ftp_pass = "ftp_pass";
copy($file, "ftp://$ftp_user:$ftp_pass#$ftp_server/PSG11_CUG_EN_03.pdf");
If you need a greater control over the writing (transfer mode, passive mode, offset, reading limit, etc), use the ftp_fput with a handle to the php://temp (or the php://memory) stream.
See Transfer in-memory data to FTP server without using intermediate file.

How to modify PHP FTP upload script to download files instead

I have found a PHP script for transferring FTP files, and it works exactly as I need for one part of my project. The script can upload files via FTP to another server just fine, and can output the progress as it goes.
The code I am using is:
$fp = fopen($local_file, 'r');
$conn_id = ftp_connect($source_ftp_server);
$login_result = ftp_login($conn_id, $source_ftp_user_name, $source_ftp_user_pass);
$ret = ftp_nb_fput($conn_id, $remote_file, $fp, FTP_BINARY);
while ($ret == FTP_MOREDATA) {
// Establish a new connection to FTP server
if(!isset($conn_id2)) {
$conn_id2 = ftp_connect($source_ftp_server);
$login_result2 = ftp_login($conn_id2, $source_ftp_user_name, $source_ftp_user_pass);
}
// Retreive size of uploaded file.
if(isset($conn_id2)) {
clearstatcache(); // <- this must be included!!
$remote_file_size = ftp_size($conn_id2, $remote_file);
}
// Calculate upload progress
$local_file_size = filesize($local_file);
if (isset($remote_file_size) && $remote_file_size > 0 ){
$i = ($remote_file_size/$local_file_size)*100;
printf("%d%% uploaded<br>", $i);
flush();
}
$ret = ftp_nb_continue($conn_id);
}
if ($ret != FTP_FINISHED) {
echo "<span style='color:red;'><b>There was an error uploading the file...</b></span><br>";
exit(1);
}
else {
echo "<br>Files successfully uploaded!<br><br>";
}
fclose($fp);
I took out some unimportant parts, such as extra information that is echoed by the script, etc.
This code works perfectly for uploading files to the other server. However, I also need to download a file from the server using FTP as well.
I'd really like to use the same code as above, with the progress indicator, etc, but am not sure how to modify this code to download a file instead of uploading one.
It may be a couple of simple changes are all that is needed.
Are there any parts of this code in particular that will need to be changed, or can this not work the same for downloads as it does for uploads?
I'd really appreciate it if someone could point me in somewhat of the right direction to sort this out.
Is it as simple as changing the ftp_nb_fput command to a ftp_nb_get command? I don't really understand all of this code so it's difficult to tell what would need to be changed.
Thanks for your help.
You are looking for ftp_get
Looks like it should be used something like the following:
$conn_id = ftp_connect($source_ftp_server);
$login_result = ftp_login($conn_id, $source_ftp_user_name, $source_ftp_user_pass);
$success = ftp_get($conn_id, $local_file, $server_file, FTP_BINARY);
http://php.net/manual/en/function.ftp-get.php
Here's the script, with the necessary modifications to make it download a file instead:
$fp = fopen($local_file2, 'w+');
$conn_id = ftp_connect($source_ftp_server);
$login_result = ftp_login($conn_id, $source_ftp_user_name, $source_ftp_user_pass);
$ret = ftp_nb_fget($conn_id, $fp, $remote_file2, FTP_BINARY);
while ($ret == FTP_MOREDATA) {
// Establish a new connection to FTP server
if(!isset($conn_id2)) {
$conn_id2 = ftp_connect($source_ftp_server);
$login_result2 = ftp_login($conn_id2, $source_ftp_user_name, $source_ftp_user_pass);
}
// Retreive size of source file.
if(isset($conn_id2)) {
clearstatcache(); // <- this must be included!!
$remote_file2_size = ftp_size($conn_id2, $remote_file2);
}
// Calculate download progress
$local_file2_size = filesize($local_file2);
if (isset($remote_file2_size) && $remote_file2_size > 0 ){
$i = ($local_file2_size/$remote_file2_size)*100;
printf("%d%% downloaded<br>", $i);
}
$ret = ftp_nb_continue($conn_id);
}
if ($ret != FTP_FINISHED) {
echo "<span style='color:red;'><b>There was an error downloading the file...</b></span><br>";
exit(1);
}
echo "<br>Files successfully downloaded!<br><br>";
fclose($fp);

ssh2_scp_send() and ssh2_scp_recv() functions are not working in php. Why?

ssh2_scp_send() function is hanging in php. Here's the code:
$debug_line_feed = "\n";
$conn = ssh2_connect($sftp_server, 22);
$return = ssh2_auth_password($conn, $sftp_user_name, $sftp_user_pass);
if ($return===true) echo "successfull connection".$debug_line_feed;
echo "uploading file".$debug_line_feed;
$local_filename = $product_feed_file_with_path;
$remote_filename = 'product_feed.txt';
ssh2_scp_send($conn, $local_filename, $remote_filename);
echo "successful".$debug_line_feed;
When i run it, it outputs "successful connection", "uploading file" then hangs. Any idea how to fix this?
I have tried a download as well with ssh2_scp_recv, and it hangs as well, with the local file being created as a 0 byte file.
My guess is that the server has a jail shell installed. At that point SCP wouldn't work but SFTP would.
recently,i use sftp to send file,linux to windows,ssh2_scp_send not work,i solve the problems use
$sftp = ssh2_sftp($conn);
$contents = file_get_contents($localPath);
$result = file_put_contents("ssh2.sftp://{$sftp}/{$remotePath}", $contents);
then works

Categories