简体   繁体   中英

Download all contents from FTP server without time limit

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM