Have you ever wanted to copy an FTP folder with all its files and subfolders locally? Well, this is even better!
This PHP code snippet synchronizes the contents of a remote FTP folder with a local one, it checks file dates and refrains from copying files whose timestamps did not change! I would have encapsulated it in a class if I had time, but this will do :-)
<?php
// we'll assume our remote folder is located on this address... ftp://web.whatever.com/folder1/folder2
$hostname = 'web.whatever.com'; // ftp host
$directory_path = 'folder1/folder2'; // this is the ftp directory path to retrieve
$base_directory_path = 'local_folder'; // this is the local folder we want to synch to
$username = 'username';
$password = 'password';
// this code will create the base directory, local_folder/folder2
$directory = explode('/', $directory_path);
$directory = $directory[count($directory) - 1];
try
{
if (!is_dir($base_directory_path.'/'.$directory))
if (!mkdir($base_directory_path.'/'.$directory))
throw new Exception('Could not create folder.', 0);
handle_url($hostname, $directory_path, $base_directory_path.'/'.$directory, $username, $password);
print "done";
}
catch (Exception $e)
{
die($e->getMessage());
}
function handle_url($hostname, $directory_path, $base_dir_path, $username, $password, $date_start_offset = FALSE)
{
if ((@ $ftp = ftp_connect($hostname)) === FALSE)
throw new Exception('Error establishing FTP connection. Do you have privileges on this server?', 1);
if (@ !ftp_login($ftp, $username, $password))
throw new Exception("Can't log in. Check username & password.", 2);
if (@ !ftp_chdir($ftp, $directory_path))
throw new Exception("Couldn't change FTP directory", 3);
if ((@ $listing = ftp_rawlist($ftp, '.')) === FALSE)
throw new Exception("Can't retrieve FTP directory listing.", 4);
foreach ($listing AS $key=>$value)
{
if ($value[0] == 'd') // directory
{
$folder_name = explode(' ', $value);
$folder_name = $folder_name[count($folder_name) - 1];
if (!is_dir($base_dir_path.'/'.$folder_name))
if (!mkdir($base_dir_path.'/'.$folder_name))
throw new Exception('Could not create folder.', 0);
handle_url($hostname, $directory_path.'/'.$folder_name, $base_dir_path.'/'.$folder_name,
$username, $password, $date_start_offset);
}
else // file
{
$file_info = explode(' ', $value);
// added this code because I found that for some reason the date sometimes starts at offset 12
// other times at offset 13, I'll assume that it may even be at a different offset! We only check
// the date offset if a previous call to handle_url had failed, and if it had succeeded, we check
// for a new offset if the current one doesn't contain a date
if ($date_start_offset === FALSE || strpos($file_info[$date_start_offset + 2], ':') === FALSE)
for ($i = 0 ; $i < count($file_info) ; $i++)
{
if (strpos($file_info[$i], ':') !== FALSE)
{
$date_start_offset = $i - 2; // the location of the month
break;
}
}
if ($date_start_offset === FALSE)
throw new Exception("Can't find file date!", 6);
$timestamp = $file_info[$date_start_offset].' '.$file_info[$date_start_offset + 1].' '.
$file_info[$date_start_offset + 2].' '.date('Y'); // month day time year
$timestamp = strtotime($timestamp);
$file_name = $file_info[count($file_info) - 1];
// does file exist and have same timestamp as the one on server? If so, just skip this file
if (is_file($base_dir_path.'/'.$file_name))
if (filemtime($base_dir_path.'/'.$file_name) == $timestamp) continue;
// get file
if (!ftp_get($ftp, $base_dir_path.'/tmp.file', $file_name, FTP_BINARY)) continue;
if (!rename($base_dir_path.'/tmp.file', $base_dir_path.'/'.$file_name))
throw new Exception("Couldn't rename file.");
// change file's date to date from server file
if (!touch($base_dir_path.'/'.$file_name, $timestamp))
throw new Exception("Couldn't change file modification date.", 5);
}
}
}
?>
Sunday, October 08, 2006
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment