Upload Entire Directory via PHP to a remote host via FTP - php

I'm using Codeigniter to create a web site, and I tried to create a function to upload the entire directory via FTP to a remote host, but nothing is working
I tried 2 functions I found, but also not working, only few files uploaded, and some files size is 0 bytes
Functions Used :
// 1St Function
public function ftp_copy($src_dir, $dst_dir) {
$d = dir($src_dir);
while($file = $d->read()) {
if ($file != "." && $file != "..") {
if (is_dir($src_dir."/".$file)) {
if (!#ftp_chdir($this->conn_id, $dst_dir."/".$file)) {
ftp_mkdir($this->conn_id, $dst_dir."/".$file);
}
ftp_copy($src_dir."/".$file, $dst_dir."/".$file);
}
else {
$upload = ftp_put($this->conn_id, $dst_dir."/".$file, $src_dir."/".$file, FTP_BINARY);
}
}
}
$d->close();
}
// 2nd Solution from Stackoverflow question
foreach (glob("/directory/to/upload/*.*") as $filename)
ftp_put($ftp_stream, basename($filename) , $filename, FTP_BINARY);
Any solution ??

If you are using codeigniter you can use $this->ftp->mirror() from their FTP Library.
http://codeigniter.com/user_guide/libraries/ftp.html
$this->load->library('ftp');
$config['hostname'] = 'ftp.example.com';
$config['username'] = 'your-username';
$config['password'] = 'your-password';
$config['debug'] = TRUE;
$this->ftp->connect($config);
$this->ftp->mirror('/path/to/myfolder/', '/public_html/myfolder/');
$this->ftp->close();

Related

How to calculate entire directory size with FTP access using PHP

I have a number of different hosting accounts set up for clients and need to calculate the amount of storage space being used on each account, which would update regularly.
I have a database set up to record each clients storage usage.
I attempted this first using a PHP file on each account, run by a Cron Job. If run manually by myself, it would output the correct filesize and update the correct size to the database, although when run from the Cron Job, it would output 0.
I then attempted to run this file from a Cron Job from the main account but figured this wouldn't actually work as my hosting would block files from another server and I would end up with the same result as before.
I am now playing around with FTP access to each account from a Cron Job from the main account which looks something like below, the only problem is I don't know how to calculate directory size rather than single file sizes using FTP access, and don't know how to reiterate this way? Hoping somebody might be able to help here before I end up going around in circles?
I will also add the previous first attempt too.
$ftp_conn = ftp_connect($ftp_host, 21, 420) or die("Could not connect to server");
$ftp_login = ftp_login($ftp_conn, $ftp_username, 'mypassword');
$total_size = 0;
$contents = ftp_nlist($ftp_conn, ".");
// output $contents
foreach($contents as $folder){
while($search == true){
if($folder == '..' || $folder == '.'){
} else {
$file = $folder;
$res = ftp_size($ftp_conn, $file);
if ($res != -1) {
$total_size = $total_size + $res;
} else {
$total_size = $total_size;
}
}
}
}
ftp_close($ftp_conn);
This doesn't work as it doesn't calculate folder sizes and I don't know how to open the reiterate using this method?
This second script did work but would only work if opened manually, and return 0 if run by the cron job.
class Directory_Calculator {
function calculate_whole_directory($directory)
{
if ($handle = opendir($directory))
{
$size = 0;
$folders = 0;
$files = 0;
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
if(is_dir($directory.$file))
{
$array = $this->calculate_whole_directory($directory.$file.'/');
$size += $array['size'];
$files += $array['files'];
$folders += $array['folders'];
}
else
{
$size += filesize($directory.$file);
$files++;
}
}
}
closedir($handle);
}
$folders++;
return array('size' => $size, 'files' => $files, 'folders' => $folders);
}
}
/* Path to Directory - IMPORTANT: with '/' at the end */
$directory = '../public_html/';
// return an array with: size, total files & folders
$array = $directory_size->size($directory);
$size_of_site = $array['size'];
echo $size_of_site;
Please bare in mind that I am currently testing and none of the MySQLi or PHP scripts are secure yet.
If your server supports MLSD command and you have PHP 7.2 or newer, you can use ftp_mlsd function:
function calculate_whole_directory($ftp_conn, $directory)
{
$files = ftp_mlsd($ftp_conn, $directory) or die("Cannot list $directory");
$result = 0;
foreach ($files as $file)
{
if (($file["type"] == "cdir") || ($file["type"] == "pdir"))
{
$size = 0;
}
else if ($file["type"] == "dir")
{
$size = calculate_whole_directory($ftp_conn, $directory."/".$file["name"]);
}
else
{
$size = intval($file["size"]);
}
$result += $size;
}
return $result;
}
If you do not have PHP 7.2, you can try to implement the MLSD command on your own. For a start, see user comment of the ftp_rawlist command:
https://www.php.net/manual/en/function.ftp-rawlist.php#101071
If you cannot use MLSD, you will particularly have problems telling if an entry is a file or folder. While you can use the ftp_size trick, as you do, calling ftp_size for each entry can take ages.
But if you need to work against one specific FTP server only, you can use ftp_rawlist to retrieve a file listing in a platform-specific format and parse that.
The following code assumes a common *nix format.
function calculate_whole_directory($ftp_conn, $directory)
{
$lines = ftp_rawlist($ftp_conn, $directory) or die("Cannot list $directory");
$result = 0;
foreach ($lines as $line)
{
$tokens = preg_split("/\s+/", $line, 9);
$name = $tokens[8];
if ($tokens[0][0] === 'd')
{
$size = calculate_whole_directory($ftp_conn, "$directory/$name");
}
else
{
$size = intval($tokens[4]);
}
$result += $size;
}
return $result;
}
Based on PHP FTP recursive directory listing.
Regarding cron: I'd guess that the cron does not start your script with a correct working directory, so you calculate a size of a non-existing directory.
Use an absolute path here:
$directory = '../public_html/';
Though you better add some error checking so that you can see yourself what goes wrong.

How Download from ftp server to local machine where codeigniter site is hosted in a VPS

I have hosted a codeigniter site in AWS which is working fine and the connection to the ftp server is also fine.
Here is my ftp class;
public function download_ftp($file_name) {
$this->load->library('ftp');
$config['hostname'] = '213.62.21.2';
$config['username'] = 'Admin';
$config['password'] = 'admin';
$config['port'] = 21;
$config['passive'] = FALSE;
$config['debug'] = TRUE;
$this->ftp->connect($config);
$found_file = FALSE;
$files = $this->ftp->list_files();
var_dump($files);
if (count($files) > 0) {
foreach ($files as $f) {
if ($f == './' . $file_name) {
$found_file = TRUE;
break;
}
}
}
if ($found_file) {
echo '<script type="text/javascript">
alert("Click OK to download file. You will be notified when the download is completed. Dont refresh the page until");
</script>';
$result = $this->ftp->download($file_name, 'C:/new/ftp/' . $file_name);
if ($result == FALSE) {
echo 'file not downloaded';
}
'C:/new/ftp/' is the local directory , the file to be downloaded.
This code downloads the file to the hosted server the client accessing the website.
How to change the path so the file would be downloaded to the clent machine?

phpseclib producing strange output

I have code which generates a text file on my server. I then need this file uploaded to another server using sftp. To start things off, I do
if(performLdapOperations()) {
sleep(10);
performFtpOperation();
}
performLdapOperations produces the text file and places it on my server, performFtpOperation takes this text file and uploads to another server. This is my function
function performFtpOperation() {
global $config;
$local_directory = getcwd() .'/outputs/';
$remote_directory = '/home/newfolder/';
$sftp = new SFTP($config::FTP_SERVER, 22, 10);
if (!$sftp->login($config::FTP_USER, $config::FTP_PASSWORD)) {
exit('Login Failed');
}
$files_to_upload = array();
/* Open the local directory form where you want to upload the files */
if ($handle = opendir($local_directory))
{
/* This is the correct way to loop over the directory. */
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
$files_to_upload[] = $file;
}
}
closedir($handle);
}
if(!empty($files_to_upload))
{
/* Now upload all the files to the remote server */
foreach($files_to_upload as $file)
{
$success = $sftp->put($remote_directory . $file,
$local_directory . $file,
NET_SFTP_LOCAL_FILE);
}
}
}
So the text file that is produces is in my outputs folder. I then want to take this file and upload to a new server to the location /home/newfolder/
Everything seems to work, and the file seems to get uploaded to the new server. However, when I open the file that has been uploaded, all it contains is the path of where the file is, nothing else. The file on my server which is in the outputs folder contains everything, for some reason something is going wrong when sending it over sftp?
Is there anything in my code that may be causing this?
Thanks
It looks like you're using the 2.0 version of phpseclib, which is namespaced. If that's the case then the problem is with this line:
$success = $sftp->put($remote_directory . $file,
$local_directory . $file,
NET_SFTP_LOCAL_FILE);
Try this:
$success = $sftp->put($remote_directory . $file,
$local_directory . $file,
SFTP::SOURCE_LOCAL_FILE);

php sftp file or folder

i am attempting to create a web based sftp page, the only part i am having problems with is trying to determin the the listed file is a file or folder. i am sucessfully listing a directory using
$connection = ssh2_connect($_SESSION['Server'], $_SESSION['Port']);
if(ssh2_auth_password($connection, $_SESSION['Username'], $_SESSION['Password']))
{
$sftp = ssh2_sftp($connection);
$dir = "ssh2.sftp://$sftp/$directory";
$handle = opendir($dir);
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
$temp=$file;
if(strlen($directory) > 0)
$Path=$directory."/".$file;
else
$Path=$file;
$statinfo = ssh2_sftp_stat($sftp, "/".$Path);
echo "$temp<br />";
}
}
closedir($handle);
}
i attempted to use the is_dir() and is_file() php function on $file which works sucessfully when working on local filesystem, but when using SFTP both come back FALSE, i attempted to use ssh2_sftp_stat() but this only gives uid, gid, size access and modified times and i dont think there is anyting that can be used to identify files of folders, if anyone has a way to resolve this i would appreaciate it greatly
Vip32
I would strongly suggest using phpseclib for SSH2 purposes. It greatly simplifies tasks like this.
Solution for your problem using phpseclib should go something like this:
include('Net/SFTP.php');
$sftp = new Net_SFTP($_SESSION['Server'] . ':' . $_SESSION['Port']);
if (!$sftp->login($_SESSION['Username'], $_SESSION['Password'])) {
exit('Login Failed');
}
foreach($sftp->rawlist($dir) as $filename => $attrs) {
if ($attr['type'] == NET_SFTP_TYPE_REGULAR) {
echo $filename . ' is a regular file!';
}
if ($attr['type'] == NET_SFTP_TYPE_DIRECTORY) {
echo $filename . ' is a directory!';
}
}
These are the file type constants phpseclib uses:
file_types = array(
1 => 'NET_SFTP_TYPE_REGULAR',
2 => 'NET_SFTP_TYPE_DIRECTORY',
3 => 'NET_SFTP_TYPE_SYMLINK',
4 => 'NET_SFTP_TYPE_SPECIAL'
);

want to download images from server

I want to transfer site from shared hosting server to dedicated server.current server has folder,which includes approx. 16000 images...we can not use FTP to download these much images.and i do not have SSH rights? how can i download images from this shared hosting server.
we can not use FTP to download these much images
Nonsense. FTP (the protocol) is perfectly capable of downloading 16000 files. If your FTP program is causing you trouble, simply pick a better FTP program. If you can handle commandline applications, wget is nice, since it supports recursion and continuation.
Unless they are located within a directory that is within the web root of a web application server you are out of luck.
Zip them all, adapted from http://davidwalsh.name/create-zip-php
<?php
function create_zip($files = array(),$destination = '',$overwrite = false) {
//if the zip file already exists and overwrite is false, return false
if(file_exists($destination) && !$overwrite) { return false; }
//vars
$valid_files = array();
//if files were passed in...
if(is_array($files)) {
//cycle through each file
foreach($files as $file) {
//make sure the file exists
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
//if we have good files...
if(count($valid_files)) {
//create the archive
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
//add the files
foreach($valid_files as $file) {
$zip->addFile($file,$file);
}
//debug
//echo 'The zip archive contains ',$zip->numFiles,' files with a status of ',$zip->status;
//close the zip -- done!
$zip->close();
//check to make sure the file exists
return file_exists($destination);
}
else
{
return false;
}
}
//glob images folder into an array
foreach (glob("*.jpg") as $filename) {
$files_to_zip[]='images/'.$filename;
}
//create the zip
$result = create_zip($files_to_zip,'my-images.zip');
if($result==true){echo'Download Images';
}else{
echo'Could not create zip';}
?>

Categories