Downloading a folder through with FTP using PHP

How can i donwload a folder from a remote host using FTP And PHP?

I have username and password and the folder to donwload...

copy()?

Let me know, thanks!


Solution 1:

<?php 
$ftp_server = "ftp.example.com"; 
$conn_id = ftp_connect ($ftp_server) 
    or die("Couldn't connect to $ftp_server"); 
    
$login_result = ftp_login($conn_id, "user", "pass"); 
if ((!$conn_id) || (!$login_result)) 
    die("FTP Connection Failed"); 

ftp_sync ("DirectoryToCopy");    // Use "." if you are in the current directory 

ftp_close($conn_id);  

// ftp_sync - Copy directory and file structure 
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://www.php.net/manual/function.ftp-get.php#90910

Solution 2:

You have these choises:

  • ftp wrapper:

    $handle = opendir('ftp://user:password@host/path/to/dir') || die();
    
    while (false !== ($file = readdir($handle))) {
      if(is_file($file)){
        $c = file_get_contents($file);
        file_put_contents('/local/'.basename($file), $c);
      }
    }
    
    closedir($handle);
    
  • using ftp extension of php

    $c = ftp_connect('host.com');
    ftp_login($c, 'file', 'password');
    ftp_chdir($c, '/remote/dir');
    $contents = ftp_nlist($c, '-la .');
    foreach($contents as $line){
      $file = preg_split('@\s+@', trim($line));
      $name = $file[8];
      $size = $file[4];
      $mode = $file[0];
      if(substr($mode, 0, 1) == '-'){
        //file
        $fd = fopen('/local/path/'.$name, 'w');
        ftp_fget ($c, $fd, $name, FTP_BINARY);
        fclose($fd);
      }else{
        //dir
      }
    }
    
  • use external program like wget or lftp

    • wget --recursive [options] ftp://user:password@host/ # see wget --help
    • lftp -c commands.txt # where commands.txt would be something like:

      connect user:[email protected]
      mget /path/to/remote /path/to/local
      

Solution 3:

Improved function from @Treffynnon

  • Improved because ftp_chdir() is very time consuming when you have 100+ files in folder
  • Will transfer hidden files like .htaccess
  • Will copy only if needed (checks exists and last modified)

<?php
$ftp_server = "ftp.xxx.com"; 
$cid = ftp_connect($ftp_server) 
    or die("Couldn't connect to $ftp_server"); 

$login_result = ftp_login($cid, "user", "pass"); 
if ((!$cid) || (!$login_result)) 
    die("FTP Connection Failed"); 

ftp_pasv($cid, true); // passive FTP connection (comment-out if needed)

ftp_sync('/folder_on_ftp/www/', '/folder_on_new_server/www');

ftp_close($cid);

umask(0); // every directory will be chmod 777

function ftp_sync($_from = null, $_to = null) {
    
    global $cid;
    
    if (isset($_from)) {
        if (!ftp_chdir($cid, $_from)) die("Dir on FTP not found: $_from");
        if (isset($_to)) {
            if (!is_dir($_to)) @mkdir($_to);
            if (!chdir($_to)) die("Dir on local not exists? $_to"); 
        }
    }
    
    $contents = ftp_mlsd($cid, '.');
    
    foreach ($contents as $p) {
        
        if ($p['type'] != 'dir' && $p['type'] != 'file') continue;
        
        $file = $p['name'];
        
        echo ftp_pwd($cid).'/'.$file;
        
        if (file_exists($file) && !is_dir($file) && filemtime($file) >= strtotime($p['modify'])) {
            echo " [EXISTS AND CURRENT]";
        }
        elseif ($p['type'] == 'file' && @ftp_get($cid, $file, $file, FTP_BINARY)) {
            echo " [COPIED]";
        }
        elseif ($p['type'] == 'dir' && @ftp_chdir($cid, $file)) {
            echo "Dir changed to $file<br>\n";
            if (!is_dir($file)) mkdir($file);
            chdir($file);
            ftp_sync();
            ftp_chdir($cid, '..');
            chdir('..');
        }
        
        echo "<br>\n";
    }
}