I want to download the contents (files, folders, and sub-folders) of a directory from a FTP server using PHP.
I was able to do it using this function:
function ftp_sync ($dir) {
global $conn_id;
if ($dir != ".") {
if (ftp_chdir($conn_id, $dir) == false) {
echo ("Change Dir Failed: $dir<BR>\r\n");
return;
}
if (!(is_dir($dir)))
mkdir($dir);
chdir ($dir);
}
$contents = ftp_nlist($conn_id, ".");
foreach ($contents as $file) {
if ($file == '.' || $file == '..')
continue;
if (#ftp_chdir($conn_id, $file)) {
ftp_chdir ($conn_id, "..");
ftp_sync ($file);
}
else
ftp_get($conn_id, $file, $file, FTP_BINARY);
}
ftp_chdir ($conn_id, "..");
chdir ("..");
}
Source: https://stackoverflow.com/a/5650503/10349407
But after some time; the script times out from the browser because it takes so long time as the contents of the folder are large.
I tried to set:
ini_set('max_execution_time', 0);
set_time_limit(0);
but I still get the error Warning: set_time_limit() has been disabled for security reasons as I am on a shared hosting.
So, my question: Is it possible to do redirects in the above PHP function so it starts a new page for each file that it downloads (this is my suggestion to prevent the timeout limit)
So a line like:
header("Location: " . __FILE__ . "?file=$file");
where it should download the file which is the value of $_GET['file'] then redirect again and so on until it finishes downloading the whole contents.
EDIT: This is my try but it doesn't work :/
function ftp_sync ($dir) {
global $conn_id;
if( isset($_GET['cd']) ) {
$dir = $_GET['cd'];
}
if ($dir != ".") {
if (ftp_chdir($conn_id, $dir) == false) {
echo ("Change Dir Failed: $dir<BR>\r\n");
return;
}
if (!(is_dir($dir)))
mkdir($dir);
chdir ($dir);
}
$contents = ftp_nlist($conn_id, ".");
foreach ($contents as $file) {
if ($file == '.' || $file == '..')
continue;
if (#ftp_chdir($conn_id, $file)) {
ftp_chdir ($conn_id, "..");
ftp_sync ($file);
header("refresh:0.5;url=" . "ftp.php" . "?file=$file&cd=" . ftp_pwd($conn_id));
die();
}
else {
ftp_get($conn_id, $file, $file, FTP_BINARY);
}
}
ftp_chdir ($conn_id, "..");
chdir ("..");
}
I finally did it on my own!
All what I needed was a way to list ALL the contents of the FTP server recursively (files, directories, sub-directories).
And I found this awesome class: https://www.phpclasses.org/package/7707-PHP-List-recursively-all-files-in-a-FTP-server.html
So, all what you've to do is to download this class and write this script which I've spent hours on (although it is simple xD).
<?php
error_reporting(0);
set_time_limit(0);
session_start();
// SETTINGS
$ftp_hostname = "";
$ftp_port = 21;
$ftp_username = "";
$ftp_password = "";
$where_to_download = "."; // Without the last slash!
// ---------------------
// NOTE: If you want to end the current session; go to http://example.com/filename.php?end
if( isset($_GET['end']) ) {
session_unset();
session_destroy();
die("Successfully ended the session.");
}
include("ftpcrawler.php");
$ftpcrawler = new ftpcrawler;
$ftpcrawler->server = "ftp://$ftp_username:$ftp_password#$ftp_hostname:$ftp_port/";
if( !isset($_SESSION['array']) ) {
$_SESSION['array'] = $ftpcrawler->crawl();
}
if( empty($_SESSION['array']) ) {
echo "Finished downloading everything , or theres no files to download.";
session_unset();
session_destroy();
die();
}
foreach($_SESSION['array'] as $item) {
if( $item['type'] == "file" ) {
$ITEM_DIRECTORY = str_replace($item['name'], "", $item['path']);
}
if( $item['type'] == "directory" ) {
$ITEM_DIRECTORY = $item['path'];
}
if (!file_exists($where_to_download . $ITEM_DIRECTORY) && !is_dir($where_to_download . $ITEM_DIRECTORY)) {
mkdir($where_to_download . $ITEM_DIRECTORY, 0777, TRUE);
}
if( $item['type'] == "file" ) {
$data = #file_get_contents("ftp://$ftp_username:$ftp_password#$ftp_hostname:$ftp_port" . $item['path']);
file_put_contents($where_to_download . $item['path'], $data);
}
unset($_SESSION['array'][$item['path']]); // Remove the item from the array.
echo "Downloaded/Created Folder " . $item['path'] . " !";
header( "refresh:0.2;url=" . basename(__FILE__) );
die();
}
?>
Save the file with the name you need and make sure that ftpcrawler.php is in the same directory of the script.
Related
I want to make a copy of ftp in a folder of my project(localhost) so I need to specify source_folder and dest_folder. My problem is that my code just save all files in my project's root and I would like to copy my ftp folder "/" into my "./copy_data" folder in my local project.
Here is my code:
function ftp_sync ($dir) {
if ($dir != ".") {
if (ftp_chdir($this->conn, $dir) == false) {
echo ("Change Dir Failed: $dir<BR>\r\n");
return;
}
if (!(is_dir($dir)))
mkdir($dir);
chdir ($dir);
}
$contents = ftp_nlist($this->conn, ".");
foreach ($contents as $file) {
if ($file == '.' || $file == '..')
continue;
if (#ftp_chdir($this->conn, $file)) {
ftp_chdir ($this->conn, "..");
$this->ftp_sync ($file);
}
else{
//ftp_get($this->conn, $file, $file, FTP_BINARY);
ftp_get($this->conn, $file, $file, FTP_BINARY);
}
}
ftp_chdir ($this->conn, "..");
chdir ("..");
}
ftp_sync('.');
Could anyone help me?
You can execute bash command from php to zip, copy and move the target folder is my recommendation
$message=shell_exec("/var/www/scripts/testscript 2>&1");
print_r($message);
Basically, my requirement is, I want to move all files from one folder to another folder using PHP scripts. Any one can help me. I am trying this, but I am getting error
$mydir = dirname( __FILE__ )."/html/images/";
if(!is_dir($mydir)){
mkdir("html/images");
}
// Move all images files
$files = glob("images/*.");
foreach($files as $file){
$file_to_go = str_replace("images/","html/images/",$file);
copy($file, $file_to_go);
}
// images folder creation using php
$mydir = dirname( __FILE__ )."/html/images";
if(!is_dir($mydir)){
mkdir("html/images");
}
// Move all images files
$files = glob("images/*.*");
foreach($files as $file){
$file_to_go = str_replace("images/","html/images/",$file);
copy($file, $file_to_go);
}
Try this :
<?php
$src = 'pictures';
$dst = 'dest';
$files = glob("pictures/*.*");
foreach($files as $file){
$file_to_go = str_replace($src,$dst,$file);
copy($file, $file_to_go);
}
?>
foreach(glob('old_directory/*.*') as $file) {
copy('old_directory/'.$file, 'new_directory/'.$file);
}
Use array_map:
// images folder creation using php
function copyFile($file) {
$file_to_go = str_replace("images/","html/images/",$file);
copy($file, $file_to_go);
}
$mydir = dirname( __FILE__ )."/html/images";
if(!is_dir($mydir)){
mkdir("html/images");
}
// Move all images files
$files = glob("images/*.*");
print_r(array_map("copyFile",$files));
This One Works for me...........
Thanks to this man
http://www.codingforums.com/php/146554-copy-one-folder-into-another-folder-using-php.html
<?php
copydir("admin","filescreate");
echo "done";
function copydir($source,$destination)
{
if(!is_dir($destination)){
$oldumask = umask(0);
mkdir($destination, 01777); // so you get the sticky bit set
umask($oldumask);
}
$dir_handle = #opendir($source) or die("Unable to open");
while ($file = readdir($dir_handle))
{
if($file!="." && $file!=".." && !is_dir("$source/$file"))
copy("$source/$file","$destination/$file");
}
closedir($dir_handle);
}
?>
This should work just fine:
// Get array of all source files
$files = scandir("source");
// Identify directories
$source = "source/";
$destination = "destination/";
// Cycle through all source files
foreach ($files as $file) {
if (in_array($file, array(".",".."))) continue;
// If we copied this successfully, mark it for deletion
if (copy($source.$file, $destination.$file))
{
$delete[] = $source.$file;
}
}
// Delete all successfully-copied files
foreach ($delete as $file)
{
unlink($file);
}
or with rename() and some error checking:
$srcDir = 'dir1';
$destDir = 'dir2';
if (file_exists($destDir)){
if (is_dir($destDir)) {
if (is_writable($destDir)) {
if ($handle = opendir($srcDir)) {
while (false !== ($file = readdir($handle))) {
if (is_file($srcDir . '/' . $file)) {
rename($srcDir . '/' . $file, $destDir . '/' . $file);
}
}
closedir($handle);
} else {
echo "$srcDir could not be opened.\n";
}
} else {
echo "$destDir is not writable!\n";
}
} else {
echo "$destDir is not a directory!\n";
}
} else {
echo "$destDir does not exist\n";
}
You can use this recursice function.
<?php
function copy_directory($source,$destination) {
$directory = opendir($source);
#mkdir($destination);
while(false !== ( $file = readdir($directory)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
if ( is_dir($source . '/' . $file) ) {
copy_directory($source . '/' . $file,$destination . '/' . $file);
}
else {
copy($source . '/' . $file,$destination . '/' . $file);
}
}
}
closedir($directory);
}
?>
Referrence : http://php.net/manual/en/function.copy.php
I had a similar situation where I needed to copy from one domain to another, I solved it using a tiny adjustment to the "very easy answer" given by "coDe murDerer" above:
Here is exactly what worked in my case, you can as well adjust to suit yours:
foreach(glob('../folder/*.php') as $file) {
$adjust = substr($file,3);
copy($file, '/home/user/abcde.com/'.$adjust);
Notice the use of "substr()", without it, the destination becomes '/home/user/abcde.com/../folder/', which might be something you don't want.
So, I used substr() to eliminate the first 3 characters(../) in order to get the desired destination which is '/home/user/abcde.com/folder/'. So, you can adjust the substr() function and also the glob() function until it fits your personal needs. Hope this helps.
by mistaken I upload my code on server with svn files and folders. I don't have access for SSH so can't run commands.
so is there any php code by using which I can delete all .svn folders from my projects.
EDIT:
Finding all the .svn folders is a complicated process to do that you need a to use recursive functions.
Link to code: http://pastebin.com/i5QMGm1C
Or view it here:
function rrmdir($dir)
{
foreach(glob($dir . '/*') as $path) {
if(is_dir($path)){
rrmdir($path);
}
else{
unlink($path);
}
}
foreach(glob($dir . '/.*') as $path) {
if(is_dir($path)){
$base_name = basename($path);
if ($base_name != '..' && $base_name != '.'){
rrmdir($path);
}
}
else{
unlink($path);
}
}
rmdir($dir);
}
function delete_dir($base, $dir)
{
static $count = 0;
foreach (glob($base . '/*') as $path){
if(is_dir($path)){
delete_dir($path, $dir);
}
}
foreach (glob($base . '/.*') as $path){
if(is_dir($path)){
$base_name = basename($path);
if ($base_name != '..' && $base_name != '.'){
if ($base_name == $dir){
rrmdir($path);
echo 'Directory (' . $path . ') Removed!<br />';
$count++;
}
else {
delete_dir($path, $dir);
}
}
}
}
return $count;
}
$base = $_SERVER['DOCUMENT_ROOT'];
$dir = '.svn';
$count = delete_dir($base, $dir);
echo 'Total: ' . $count . ' Folders Removed!';
I get a solution here it is
copied from lateralcode with little modification
$path = $_SERVER['DOCUMENT_ROOT'].'/work/remove-svn-php/'; // path of your directory
header( 'Content-type: text/plain' ); // plain text for easy display
// preconditon: $dir ends with a forward slash (/) and is a valid directory
// postcondition: $dir and all it's sub-directories are recursively
// searched through for .svn directories. If a .svn directory is found,
// it is deleted to remove any security holes.
function removeSVN( $dir ) {
//echo "Searching: $dir\n\t";
$flag = false; // haven't found .svn directory
$svn = $dir . '.svn';
if( is_dir( $svn ) ) {
if( !chmod( $svn, 0777 ) )
echo "File permissions could not be changed (this may or may not be a problem--check the statement below).\n\t"; // if the permissions were already 777, this is not a problem
delTree( $svn ); // remove the .svn directory with a helper function
if( is_dir( $svn ) ) // deleting failed
echo "Failed to delete $svn due to file permissions.";
else
echo "Successfully deleted $svn from the file system.";
$flag = true; // found directory
}
if( !$flag ) // no .svn directory
echo 'No .svn directory found.';
echo "\n\n";
$handle = opendir( $dir );
while( false !== ( $file = readdir( $handle ) ) ) {
if( $file == '.' || $file == '..' ) // don't get lost by recursively going through the current or top directory
continue;
if( is_dir( $dir . $file ) )
removeSVN( $dir . $file . '/' ); // apply the SVN removal for sub directories
}
}
// precondition: $dir is a valid directory
// postcondition: $dir and all it's contents are removed
// simple function found at http://www.php.net/manual/en/function.rmdir.php#93836
function delTree( $dir ) {
$files = glob( $dir . '*', GLOB_MARK ); // find all files in the directory
foreach( $files as $file ) {
if( substr( $file, -1 ) == '/')
delTree( $file ); // recursively apply this to sub directories
else
unlink( $file );
}
if ( is_dir( $dir ) ){
//echo $dir;
// die;
rmdir( $dir ); // remove the directory itself (rmdir only removes a directory once it is empty)
}
}
// remove all .svn directories in the
// current directory and sub directories
// (recursively applied)
removeSVN($path);
$path = '/home/username/www/;
if($zip = new ZipArchive){
if($zip->open('backup_'. time() .'.zip', ZipArchive::CREATE)){
if(false !== ($dir = opendir($path))){
while (false !== ($file = readdir($dir))){
if ($file != '.' && $file != '..' && $file != 'aaa'){
$zip->addFile($path . $file);
echo 'Adding '. $file .' to path '. $path . $file .' <br>';
}
}
}
else
{
echo 'Can not read dir';
}
$zip->close();
}
else
{
echo 'Could not create backup file';
}
}
else
{
echo 'Could not launch the ZIP libary. Did you install it?';
}
Hello again Stackoverflow! I want to backup a folder with all its content including (empty) subfolders and every file in them, whilst excluding a single folder (and ofcourse . and ..). The folder that needs to be excluded is aaa.
So when I run this script (every folder does have chmod 0777) it runs without errors, but the ZIP file doesn't show up. Why? And how can I solve this?
Thanks in advance!
have you tried to access the zip folder via PHP rather than looking in FTP as to whether it exists or not - as it might not appear immediately to view in FTP
function addFolderToZip($dir, $zipArchive, $zipdir = ''){
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
//Add the directory
if(!empty($zipdir)) $zipArchive->addEmptyDir($zipdir);
// Loop through all the files
while (($file = readdir($dh)) !== false) {
//If it's a folder, run the function again!
if(!is_file($dir . $file)){
// Skip parent and root directories, and any other directories you want
if( ($file !== ".") && ($file !== "..") && ($file !== "aa")){
addFolderToZip($dir . $file . "/", $zipArchive, $zipdir . $file . "/");
}
}else{
// Add the files
$zipArchive->addFile($dir . $file, $zipdir . $file);
}
}
}
}
}
After a while of fooling around this is what I found working. Use it as seen below.
$zipArchive = new ZipArchive;
$name = 'backups\backup_'. time() .'.zip';
$zipArchive->open($name, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE);
addFolderToZip($path, $zipArchive);
Here's my answer, checks if the modification time is greater then something as well.
<?php
$zip = new ZipArchive;
$zip_name = md5("backup".time()).".zip";
$res = $zip->open($zip_name, ZipArchive::CREATE);
$realpath = str_replace('filelist.php','',__FILE__);
$path = realpath('.');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
if (is_file($object)) {
$file_count ++;
$epoch = $object->getMTime();
if($epoch>='1374809360'){ // Whatever date you want to start at
$array[] = str_replace($realpath,'',$object->getPathname());
}
}
}
foreach($array as $files) {
$zip->addFile($files);
}
$zip->close();
echo $zip_name.'-'.$file_count.'-'.$count_files;
?>
I need a script to copy a file to every dir and subdir inside a specific folder.
Inside a folder called 'projects' i have several folders with several folders inside them (and so on), i need a script that checks if there is a specific file in that folder, if exist, then do nothing, if not, copy it.
I need to do this in php...
Can you help?
i hope this code can help you for what you want
$maindir=".";
mylistFolderFiles($maindir);
function mylistFolderFiles($dir){
$file = 'example.txt';
$ffs = scandir($dir);
foreach($ffs as $ff){
if($ff != '.' && $ff != '..'){
if(is_dir($dir.'/'.$ff)) {
$newfile=$dir.'/'.$ff .'/'. $file ;
if (!copy($file, $newfile)) {
echo "failed to copy $file...\n";
}
mylistFolderFiles($dir.'/'.$ff);
}
}
}
}
This would copy all files , all folders and its content .... from cunnrent directory to target .. using RecursiveDirectoryIterator and RecursiveIteratorIterator
echo "<pre>";
mkdirRecursive($target);
if (! is_writable($target)) {
echo "You don't have permission wo write to ", $target, PHP_EOL;
}
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
while ( $it->valid() ) {
if (! $it->isDot()) {
$name = $it->key();
$final = $target . str_replace($dir, "", $name);
if (! mkdirRecursive(dirname($final))) {
echo "Can Create Directory : ", dirname($final), PHP_EOL;
continue;
}
if (! #copy($name, $final)) {
echo "Can't Copy : ", dirname($final), PHP_EOL;
continue;
}
echo "Copied ", basename($name), " to ", dirname($final), PHP_EOL;
}
$it->next();
}
function mkdirRecursive($pathname, $mode = 0777) {
is_dir(dirname($pathname)) || mkdirRecursive(dirname($pathname), $mode);
return is_dir($pathname) || #mkdir($pathname, $mode);
}