Remove Old Remote FTP Folders - php

I've written a MySQL database backup script which store backup files in remote FTP server. It creates some folders in root named by database name, then in each of them it creates some folders named by current date (Format: yyyy-mm-dd), and it these folders it uploads the backup files named by exact time.
I also need to remove old second level folders (which are named by date); I mean the folders older than 4 days. This is the part I've problem with. I tried some codes with ftp_nlist and I could list folders with it, I also ftp_mdtm to get the creation date and compare it with expiration date. But the result was not okay. Here is my code:
...
$skip = array('.', '..', '.ftpquota', '.htaccess');
$expire_date = date('Y-m-d', strtotime('-4 days', time()));
$ff_list = ftp_nlist($con, $db_dir);
foreach($ff_list as $item)
{
if(in_array($item, $skip))
{
continue;
}
$mod_time = ftp_mdtm($con, $item);
if(strtotime($expire_date ) >= $mod_time)
{
ftp_rmdir($con, $item);
}
}
...
Please attend I need to remove the old folders with all of their contents, So I need the suitable remove command (I don't know if ftp_rmdir works properly).

your using the correct command ftp_rmdir
http://php.net/manual/en/function.ftp-rmdir.php
but i bet the problem is that this function, like rmdir, requires the directory be empty.
here's a recursive delete function WARNING! UNTESTED!
//credentials
$host = "ftp server";
$user = "username";
$pass = "password";
//connect
$handle = #ftp_connect($host) or die("Could not connect to {$host}");
//login
#ftp_login($handle, $user, $pass) or die("Could not login to {$host}");
function recursiveDelete($directory){
//try to delete
if( !(#ftp_rmdir($handle, $directory) || #ftp_delete($handle, $directory)) ){
//if the attempt to delete fails, get the file listing
$filelist = #ftp_nlist($handle, $directory);
//loop through the file list and recursively delete each file in the list
foreach($filelist as $file){
recursiveDelete($file);
}
//if the file list is empty, delete the directory we passed
recursiveDelete($directory);
}
}

Try this :
if(strtotime($expire_date ) >= strtotime($mod_time))

Related

On creating zip file by php I get two files instead of one

I'm struggling around with a simple PHP functionality: Creating a ZIP Archive with some files in.
The problem is, it does not create only one file called filename.zip but two files called filename.zip.a07600 and filename.zip.b07600. Pls. see the following screenshot:
The two files are perfect in size and I even can rename each of them to filename.zip and extract it without any problems.
Can anybody tell me what is going wrong???
function zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path = array(), $files_array = array()) {
// Archive File Name
$archive_file = $archiveDir."/".$archive_file_name;
// Time-to-live
$archiveTTL = 86400; // 1 day
// Delete old zip file
#unlink($archive_file);
// Create the object
$zip = new ZipArchive();
// Create the file and throw the error if unsuccessful
if ($zip->open($archive_file, ZIPARCHIVE::CREATE) !== TRUE) {
$response->res = "Cannot open '$archive_file'";
return $response;
}
// Add each file of $file_name array to archive
$i = 0;
foreach($files_array as $value){
$expl = explode("/", $value);
$file = $expl[(count($expl)-1)];
$path_file = $file_path[$i] . "/" . $file;
$size = round((filesize ($path_file) / 1024), 0);
if(file_exists($path_file)){
$zip->addFile($path_file, $file);
}
$i++;
}
$zip->close();
// Then send the headers to redirect to the ZIP file
header("HTTP/1.1 303 See Other"); // 303 is technically correct for this type of redirect
header("Location: $archive_file");
exit;
}
The code which calls the function is a file with a switch-case... it is called itself by an ajax-call:
case "zdl":
$files_array = array();
$file_path = array();
foreach ($dbh->query("select GUID, DIRECTORY, BASENAME, ELEMENTID from SMDMS where ELEMENTID = ".$osguid." and PROJECTID = ".$osproject.";") as $subrow) {
$archive_file_name = $subrow['ELEMENTID'].".zip";
$archiveDir = "../".$subrow['DIRECTORY'];
$files_array[] = $archiveDir.DIR_SEPARATOR.$subrow['BASENAME'];
$file_path[] = $archiveDir;
}
zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path, $files_array);
break;
One more code... I tried to rename the latest 123456.zip.a01234 file to 123456.zip and then unlink the old 123456.zip.a01234 (and all prior added .a01234 files) with this function:
function zip_file_exists($pathfile){
$arr = array();
$dir = dirname($pathfile);
$renamed = 0;
foreach(glob($pathfile.'.*') as $file) {
$path_parts = pathinfo($file);
$dirname = $path_parts['dirname'];
$basename = $path_parts['basename'];
$extension = $path_parts['extension'];
$filename = $path_parts['filename'];
if($renamed == 0){
$old_name = $file;
$new_name = str_replace(".".$extension, "", $file);
#copy($old_name, $new_name);
#unlink($old_name);
$renamed = 1;
//file_put_contents($dir."/test.txt", "old_name: ".$old_name." - new_name: ".$new_name." - dirname: ".$dirname." - basename: ".$basename." - extension: ".$extension." - filename: ".$filename." - test: ".$test);
}else{
#unlink($file);
}
}
}
In short: copy works, rename didn't work and "unlink"-doesn't work at all... I'm out of ideas now... :(
ONE MORE TRY: I placed the output of $zip->getStatusString() in a variable and wrote it to a log file... the log entry it produced is: Renaming temporary file failed: No such file or directory.
But as you can see in the graphic above the file 43051221.zip.a07200 is located in the directory where the zip-lib opens it temporarily.
Thank you in advance for your help!
So, after struggling around for days... It was so simple:
Actually I work ONLY on *nix Servers so in my scripts I created the folders dynamically with 0777 Perms. I didn't know that IIS doesn't accept this permissions format at all!
So I remoted to the server, right clicked on the folder Documents (the hierarchically most upper folder of all dynamically added files and folders) and gave full control to all users I found.
Now it works perfect!!! The only thing that would be interesting now is: is this dangerous of any reason???
Thanks for your good will answers...
My suspicion is that your script is hitting the PHP script timeout. PHP zip creates a temporary file to zip in to where the filename is yourfilename.zip.some_random_number. This file is renamed to yourfilename.zip when the zip file is closed. If the script times out it will probably just get left there.
Try reducing the number of files to zip, or increasing the script timeout with set_time_limit()
http://php.net/manual/en/function.set-time-limit.php

Create directory based on current date

At the moment I have a directory called showcase in my root folder. When uploading a file, I want to check if a directory exists and if not, create it based on the current date, and then move the file to that folder.
$dateYear = date('Y');
$dateMonth = date('M');
$dateDay = date('d');
if (!is_dir("/showcase/$dateYear/$dateMonth/$dateDay")) {
mkdir("/showcase/$dateYear/$dateMonth/$dateDay");
}
if (move_uploaded_file($fileTmpLoc,"/showcase/$dateYear/$dateMonth/$dateDay/$newName")){
// stuff
}
$newName is the file's name, e.g. SajdaT.jpg. This code doesn't do anything for me. How can I create something that does what I want?
e.g.
/showcase/2015/09/02 create if it doesn't exist, then move a file to it like
/showcase/2015/09/02/SajdaT.jpg
Pass recursive attribute as true with the method.
<?php
// Desired folder structure
$structure = './dir1/dir2/dir3/';
// To create the nested structure, the $recursive parameter
// to mkdir() must be specified.
if (!mkdir($structure, 0777, true)) {
die('Failed to create folders...');
}
// ...
?>

How can I download the most recent file on FTP with PHP?

On FTP server has some files. For any hour on this server is uploading new files. I'd like to download last file. How can I get last uploaded file from this server? All files are with different names.
I used folowing script to downloading one file.
$conn = ftp_connect("ftp.testftp.com") or die("Could not connect");
ftp_login($conn,"user","pass");
ftp_get($conn,"target.txt","source.txt",FTP_ASCII);
ftp_close($conn);
Thanks in advance !!!
There is no way to be sure which file is the most recent, as there is no such thing as an "uploaded time" attribute. You didn't mention much about the FTP server, but if you have some level of management over the uploads, you could ensure that the last modified time is set on upload. Whether this ends up working is down to your FTP server and possibly clients.
Assuming your modified times are equivalent to upload times, you could do something like this:
// connect
$conn = ftp_connect('ftp.addr.com');
ftp_login($conn, 'user', 'pass');
// get list of files on given path
$files = ftp_nlist($conn, '');
$mostRecent = array(
'time' => 0,
'file' => null
);
foreach ($files as $file) {
// get the last modified time for the file
$time = ftp_mdtm($conn, $file);
if ($time > $mostRecent['time']) {
// this file is the most recent so far
$mostRecent['time'] = $time;
$mostRecent['file'] = $file;
}
}
ftp_get($conn, "target.txt", $mostRecent['file'], FTP_ASCII);
ftp_close($conn);
ftp_rawlist($conn);
extract latest filename and get it.

Create diectory (ftp_mkdir) only if files exist

I currently have a program that connects to an ftp directory, if it finds csv files, runs a script, then after the script has run on the files, it creates a back up folder with the date and moves the csv files to this newly created back up folder in the ftp directory.
However, if there are no csv files in the root directory, I do not want a backup folder to be created, as there are no files to move. I know the solution is probably really simple but I cannot seem to figure it out!
logMessage("Creating backups");
$ftp_connection = #ftp_connect($ftp_url, $ftp_port, 6000);
if(!#ftp_login($ftp_connection, $ftp_username, $ftp_password )) {
logMessage("Could not connect to FTP: [$ftp_url], with Username: [$ftp_username], and Password: [$ftp_password]");
die();
}
$date = date('Y_m_d_(His)');
$newBackup = $ftp_root."/".$ftp_backup."backup_$date";
if (ftp_mkdir($ftp_connection, $newBackup)) {
logMessage ("Successfully created [$newBackup\n]");
foreach($filesToProcess as $file){
$pathData = pathinfo($file);
if(isset($pathData['extension']) && $pathData['extension'] == 'csv'){
if(!#ftp_rename($ftp_connection,
$ftp_root.'/'.$file,
$newBackup."/".$file)
){
logMessage("Unable to move file: $file")
}
}
}
}
You have used, foreach($filesToProcess as $file) ,so in $filesToProcess it's array of files. you can use, count($filesToProcess) first count number of files, then if count>0 execute code.
// $csv = your checks for string ending to .csv
$ftp_files = ftp_nlist($ftp_connection, ".");
foreach ($ftp_files = $files) {
if ($files = $csv) {
// makedir
maybe something like this in very basic syntax. ftp_nlist returns an array of all files in a particular directory.

How to compare two file structures in PHP?

I have a function which gives me the complete file structure upto n-level,
function getDirectory($path = '.', $ignore = '') {
$dirTree = array ();
$dirTreeTemp = array ();
$ignore[] = '.';
$ignore[] = '..';
$dh = #opendir($path);
while (false !== ($file = readdir($dh))) {
if (!in_array($file, $ignore)) {
if (!is_dir("$path/$file")) {
//display of file and directory name with their modification time
$stat = stat("$path/$file");
$statdir = stat("$path");
$dirTree["$path"][] = $file. " === ".
date('Y-m-d H:i:s', $stat['mtime']) . " Directory ==
".$path."===". date('Y-m-d H:i:s', $statdir['mtime']) ;
} else {
$dirTreeTemp = getDirectory("$path/$file", $ignore);
if (is_array($dirTreeTemp))$dirTree =
array_merge($dirTree, $dirTreeTemp);
}
}
}
closedir($dh);
return $dirTree;
}
$ignore = array('.htaccess', 'error_log', 'cgi-bin', 'php.ini', '.ftpquota');
//function call
$dirTree = getDirectory('.', $ignore);
//file structure array print
print_r($dirTree);
Now here my requirement is , I have two sites
The Development/Test Site- where i do
testing of all the changes
The Production Site- where I finally
post all the changes as per test in
development site
Now, for example, I have tested an image upload in the Development/test site, and i found it appropriate to publish on Production site then i will completely transfer the Development/Test DB detail to Production DB, but now I want to compare the files structure as well to transfer the corresponding image file to Production folder.
There could be the situation when I update the image by editing the image and upload it with same name, now in this case the image file would be already present there, which will restrict the use of "file_exist" logic, so for these type of situations....HOW CAN I COMPARE THE TWO FILE STRUCTURE TO GET THE SYNCHRONIZATION DONE AS PER REQUIREMENT??
EDITED
the requirement has to be a script, which I am going to need as a joomla component functionality.. please reply as per this.
I would suggest using rsync for this.

Categories