While trying to list the files present in a remote sftp location using php, I get this error:
Error 324 (net::ERR_EMPTY_RESPONSE):
The server closed the connection without sending any data. On my another lamp server the same code works fine. Please point where I am missing something if you can help please. Thanks in advance.
function listBuildFiles() {
global $sftp_host, $sftp_username, $sftp_password, $sftp_path;
$connection = ssh2_connect($sftp_host);
// Authenticate
if (!ssh2_auth_password($connection, $sftp_username, $sftp_password)) {
throw new Exception('Unable to connect.');
}
// Create our SFTP resource
if (!$sftp = ssh2_sftp($connection)) {
throw new Exception('Unable to create SFTP connection.');
}
/**
* Now that we have our SFTP resource, we can open a directory resource
* to get us a list of files. Here we will use the $sftp resource in
* our address string as I previously mentioned since our ssh2://
* protocol allows it.
*/
$files = array();
$dirHandle = opendir("ssh2.sftp://$sftp$sftp_path");
$i=0;
// Properly scan through the directory for files, ignoring directory indexes (. & ..)
while (false !== ($file = readdir($dirHandle))) {
if ($file != '.' && $file != '..') {
$files[$i] = $file;
$i++;
}
}
echo '<select name="buildName">';
echo '<option>Please Select a build</option>';
foreach ($files as $filename) {
echo "<option value=\"$filename\">$filename</option>";
}
echo '</select>';
ssh2_exec($connection, "exit");
Thanks,
Ujjwal
Just to make sure there is no problem on the server side you can open a console and try a raw ssh connection in verbose mode:
ssh -v youruser#yourhost.com
this traces all the interactions between server and client, maybe gives you some clue from the server side.
With phpseclib, a pure PHP SFTP implementation, you can see the full logs of what's going on. Example:
<?php
include('Net/SFTP.php');
define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX);
$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');
echo $ssh->getLog();
print_r($ssh->getErrors());
?>
The developer of phpseclib is pretty proactive about providing support too so if you can't figure it out from the logs or error messages (s)he probably can.
Related
I have a code:
scandir("ssh2.sftp://" . intval($sftpHandle) . $remoteDir);
Why the same code works for one server but doesn't for another?
There is a files on both servers. I can manage them via Filezilla without problems.
The first one just returns array('.') even if there is a lot of files, another one returns array('file1', 'file2', 'file3', etc)
Even if I cannot list a files using scandir(), command ssh2_scp_recv($sshHandle, $remoteDir/file1, $localDir/file1) works fine.
Also ssh2_exec($sshHandle, "ls $remoteDir") works fine to me.
Please note that I'm using $ftpHandle for scandir() but $sshHandle for ssh2_* functions.
Using $sshHandle for scandir() cause "Segmentation fault" error.
I know that I can workaround this by parsing ssh2_exec($sshHandle, "ls $remoteDir") output, but would prefer do it right way if possible.
My PHP version is 7.0.31
This should work probably
$connection = ssh2_connect($url);
// login
if (!ssh2_auth_password($connection, $username, $password)) throw new Exception('Unable to connect server.');
// Create SFTP resource
if (!$sftp = ssh2_sftp($connection)) throw new Exception('Unable to create connection.');
$localDir = '/path/to/local/dir';
$remoteDir = '/path/to/remote/dir';
// download all the files or list all
$files = scandir('ssh2.sftp://' . $sftp . $remoteDir);
if (!empty($files)) {
foreach ($files as $file) {
if ($file != '.' && $file != '..') {
// here you can print files using $file
// or download file by uncommenting below line
//ssh2_scp_recv($connection, "$remoteDir/$file", "$localDir/$file");
}
}
}
This is my code to send single file from local to SFTP server. Single file successfully send.
I want to send one folder from local to SFTP server , but i dont know how to send one folder. i need help
<?php
$src = 'xxxxxxx';
$filename = 'test.txt';
$dest = 'xxxxxxxx'.$filename;
// set up sftp ssh-sftp connection
$connection = ssh2_connect('xxxxxx', 22);
ssh2_auth_password($connection, 'username', 'password');
// Create SFTP session
$sftp = ssh2_sftp($connection);
$sftpStream = #fopen('ssh2.sftp://'.$sftp.$dest, 'w');
try {
if (!$sftpStream) {
throw new Exception("Could not open remote file: $dest");
}
$data_to_send = #file_get_contents($src);
if ($data_to_send === false) {
throw new Exception("Could not open local file: $src.");
}
if (#fwrite($sftpStream, $data_to_send) === false) {
throw new Exception("Could not send data from file: $src.");
} else {
//Upload was successful, post-upload actions go here...
}
fclose($sftpStream);
} catch (Exception $e) {
error_log('Exception: ' . $e->getMessage());
fclose($sftpStream);
}
?>
ssh2_scp_send in php looks like just support sending file.
maybe these ways work:
1.compress folder, send the compressed file
2.use ssh2 to mkdir, then send each file iteratively
3.try with system() function to excute cmd line order "scp -r folder_path user#host:target_path"
I'm trying to download images from a remote FTP server and upload them to our own rackspace account. This goes fine for about 3000 images but then it crashes and gives me the following error:
exception with message 'ftp_fget(): Transfer complete.'
We've tried changing the code to use ftp_get(), to not use a temp file to store it in, but it always resulted in the same error. It always fails on the same files, if I were to delete a couple of files that were already downloaded and run the scripts again it has no problem downloading them... it just fails again once it hits those specific images on the FTP server. I've tried downloading those images manually from the server and it worked, it seems nothing is wrong with them.
This is basically the code that does it:
$this->handle = ftp_connect($ftpurl);
$loggedIn = ftp_login($this->handle, $ftpusername, $ftppassword);
if ($loggedIn === false) {
throw new Exception('Can\'t login to FTP server');
}
if ($this->handle === false) {
throw new Exception('Could not connect to the given url');
}
ftp_pasv($this->handle, true);
$fileList = ftp_nlist($this->handle, '.');
if (count($fileList) === 0) {
throw new Exception('No files found on FTP-server');
}
foreach($fileList as $filename) {
try {
$container->getObject($filename);
// Image already exists, rackspace has no convenient hasImage() function
} catch (Exception $ex) {
$temp = tmpfile();
ftp_fget($this->handle, $temp, $filename, FTP_BINARY);
//upload $tmp to rackspace
}
}
Any ideas what could be the issue here?
I am using the PECL ssh2 module to output XML data to a sftp server. I have two entirely separate PHP scripts which gather different data and send the output to different file on the stfp server.
CUSTOMER EXPORT:
$conn = ssh2_connect(SFTP_SERVER, SFTP_PORT);
ssh2_auth_password($conn, SFTP_USER, SFTP_PWD);
$sftp = ssh2_sftp($conn);
$file = 'ssh2.sftp://' . $sftp . CUSTOMER_EXPORT_PATH . CUSTOMER_EXPORT_FILENAME;
$doc = new DOMDocument('1.0','UTF-8');
CustomerExportXML($doc);
if (file_exists($file)) {
unlink($file);
}
$bytes_saved = $doc->save($file);
PRODUCT EXPORT:
$conn = ssh2_connect(SFTP_SERVER, SFTP_PORT);
ssh2_auth_password($conn, SFTP_USER, SFTP_PWD);
$sftp = ssh2_sftp($conn);
$file = 'ssh2.sftp://' . $sftp . PRODUCT_EXPORT_PATH . PRODUCT_EXPORT_FILENAME;
$doc = new DOMDocument('1.0','UTF-8');
ProductExportXML($doc);
if (file_exists($file)) {
unlink($file);
}
$bytes_saved = $doc->save($file);
In each case the XxxExportXML($doc) function takes a couple of minutes to gather the relevant data and stuff it in to $doc.
Each script works as is and exports the correct data to the correct place.
The problem is when their execution overlaps only the last one executed actually writes to the sftp server. If I echo out the $file variable then in each case they both have the same resource ID ie ssh2.sftp://ResourceID#150/Customer/Customer.xml and ssh2.sftp://ResourceID#150/Product/Product.xml
So my question is why are these two processes interfering with each other and how do I fix it so they can both be run at the same time?
So they're two different scripts? That's... weird. Maybe try phpseclib, a pure PHP SFTP implementation, instead. eg.
<?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');
How can I check if a specific file exists on a remote server using PHP via FTP connections?
Some suggestions:
Use ftp_size, which returns -1 if it doesn't exist: http://www.php.net/manual/en/function.ftp-size.php
Use fopen, e.g. fopen("ftp://user:password#example.com/somefile.txt", "r")
Use ftp_nlist, check to see if the filename you want is in the list: http://www.php.net/manual/en/function.ftp-nlist.php
I used this, a bit easier:
// the server you wish to connect to - you can also use the server ip ex. 107.23.17.20
$ftp_server = "ftp.example.com";
// set up a connection to the server we chose or die and show an error
$conn_id = ftp_connect($ftp_server) or die("Couldn't connect to $ftp_server");
ftp_login($conn_id,"ftpserver_username","ftpserver_password");
// check if a file exist
$path = "/SERVER_FOLDER/"; //the path where the file is located
$file = "file.html"; //the file you are looking for
$check_file_exist = $path.$file; //combine string for easy use
$contents_on_server = ftp_nlist($conn_id, $path); //Returns an array of filenames from the specified directory on success or FALSE on error.
// Test if file is in the ftp_nlist array
if (in_array($check_file_exist, $contents_on_server))
{
echo "<br>";
echo "I found ".$check_file_exist." in directory : ".$path;
}
else
{
echo "<br>";
echo $check_file_exist." not found in directory : ".$path;
};
// output $contents_on_server, shows all the files it found, helps for debugging, you can use print_r() as well
var_dump($contents_on_server);
// remember to always close your ftp connection
ftp_close($conn_id);
Functions used: (thanks to middaparka)
Login using ftp_connect
Get the remote file list via ftp_nlist
Use in_array to see if the file was present in the array
Just check the size of a file. If the size is -1, it doesn't exist, so:
$file_size = ftp_size($ftp_connection, "example.txt");
if ($file_size != -1) {
echo "File exists";
} else {
echo "File does not exist";
}
If the size is 0, the file does exist, it's just 0 bytes.
Source
A general solution would be to:
Login using ftp_connect
Navigate to the relevant directory via ftp_chdir
Get the remote file list via ftp_nlist or ftp_rawlist
Use in_array to see if the file was present in the array returned by ftp_rawlist
That said, you could potentially simply use file_exists if you have the relevant URL wrappers available. (See the PHP FTP and FTPS protocols and wrappers manual page for more information.)
This is an optimization of #JohanPretorius solution, and an answer for comments about "slow and inefficient for large dirs" of #Andrew and other: if you need more than one "file_exist checking", this function is a optimal solution.
ftp_file_exists() caching last folder
function ftp_file_exists(
$file, // the file that you looking for
$path = "SERVER_FOLDER", // the remote folder where it is
$ftp_server = "ftp.example.com", //Server to connect to
$ftp_user = "ftpserver_username", //Server username
$ftp_pwd = "ftpserver_password", //Server password
$useCache = 1 // ALERT: do not $useCache when changing the remote folder $path.
){
static $cache_ftp_nlist = array();
static $cache_signature = '';
$new_signature = "$ftp_server/$path";
if(!$useCache || $new_signature!=$cache_signature)
{
$useCache = 0;
//$new_signature = $cache_signature;
$cache_signature = $new_signature;
// setup the connection
$conn_id = ftp_connect($ftp_server) or die("Error connecting $ftp_server");
$ftp_login = ftp_login($conn_id, $ftp_user, $ftp_pwd);
$cache_ftp_nlist = ftp_nlist($conn_id, $path);
if ($cache_ftp_nlist===FALSE)die("erro no ftp_nlist");
}
//$check_file_exist = "$path/$file";
$check_file_exist = "$file";
if(in_array($check_file_exist, $cache_ftp_nlist))
{
echo "Found: ".$check_file_exist." in folder: ".$path;
}
else
{
echo "Not Found: ".$check_file_exist." in folder: ".$path;
};
// use for debuging: var_dump($cache_ftp_nlist);
if(!$useCache) ftp_close($conn_id);
} //function end
//Output messages
echo ftp_file_exists("file1-to-find.ext"); // do FTP
echo ftp_file_exists("file2-to-find.ext"); // using cache
echo ftp_file_exists("file3-to-find.ext"); // using cache
echo ftp_file_exists("file-to-find.ext","OTHER_FOLDER"); // do FTP
You can use ftp_nlist to list all the files on the remote server. Then you should search into the result array to check if the file what you was looking for exists.
http://www.php.net/manual/en/function.ftp-nlist.php
The code has been written by: #Drmzindec should be change a little:
if (in_array($check_file_exist, $contents_on_server))
to
if (in_array($file, $contents_on_server))