简体   繁体   English

使用PHP通过FTP下载文件夹

[英]Downloading a folder through with FTP using PHP

How can i donwload a folder from a remote host using FTP And PHP?如何使用 FTP 和 PHP 从远程主机下载文件夹?

I have username and password and the folder to donwload...我有用户名和密码以及要下载的文件夹...

copy()?复制()?

Let me know, thanks!让我知道,谢谢!

<?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: http://www.php.net/manual/es/function.ftp-get.php#90910来源: http : //www.php.net/manual/es/function.ftp-get.php#90910

You have these choises:你有这些选择:

  • ftp wrapper: ftp 包装器:

     $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使用 php 的 ftp 扩展

    $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 或 lftp

    • wget --recursive [options] ftp://user:password@host/ # see wget --help wget --recursive [options] ftp://user:password@host/ # 见 wget --help
    • lftp -c commands.txt # where commands.txt would be something like: lftp -c commands.txt # 其中 commands.txt 将类似于:

       connect user:password@ftp.host.com mget /path/to/remote /path/to/local

Improved function from @Treffynnon来自@Treffynnon 的改进功能

  • Improved because ftp_chdir() is very time consuming when you have 100+ files in folder改进,因为当文件夹中有 100 多个文件时,ftp_chdir() 非常耗时
  • Will transfer hidden files like .htaccess将传输隐藏文件,如 .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";
    }
}

I've just released two new libraries to do such things in FTP and SFTP .我刚刚发布了两个新库来在FTPSFTP 中做这样的事情。

Recursively copy files and folders on remote SFTP server (If local_path ends with a slash upload folder content otherwise upload folder itself)递归复制远程 SFTP 服务器上的文件和文件夹(如果 local_path 以斜杠结尾,则上传文件夹内容,否则上传文件夹本身)

Ftp::upload_dir($server, $user, $password, $local_path, $remote_path, $port = 22);

Download a directory from remote FTP server (If remote_dir ends with a slash download folder content otherwise download folder itself)从远程 FTP 服务器下载目录(如果 remote_dir 以斜杠结尾,则下载文件夹内容,否则下载文件夹本身)

Ftp::download_dir($server, $user, $password, $remote_dir, $local_dir, $port = 22);

For the code here it is but you will need the entire class for small utilities functions dependencies.对于此处的代码,您将需要整个类来获取小型实用程序函数依赖项。

/**
 * Download a directory from remote FTP server
 *
 * If remote_dir ends with a slash download folder content
 * otherwise download folder itself
 *
 * @param string $server 
 * @param string $user
 * @param string $password
 * @param string $remote_dir
 * @param string $local_dir
 * @param int $port
 *
 * @return bool $downloaded
 *
 */
public static function download_dir($server, $user, $password, $remote_dir, $local_dir, $port = 21)
{
    $downloaded = false;
    try
    {
        if(is_dir($local_dir) && is_writable($local_dir))
        {
            if(false !== $cid = Ftp::login($server, $user, $password, $port))
            {
                # If remote_dir do not ends with /
                if(!HString::ends_with($remote_dir, '/'))
                {
                    # Create fisrt level directory on local filesystem
                    $local_dir = rtrim($local_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . basename($remote_dir);
                    mkdir($local_dir);
                }

                # Remove trailing slash
                $local_dir = rtrim($local_dir, DIRECTORY_SEPARATOR);
                $downloaded = Ftp::download_all($cid, $remote_dir, $local_dir); 
                ftp_close($cid); 
            }
        }
        else
        {
            throw new Exception("Local directory does not exist or is not writable", 1);
        }
    }
    catch(Exception $e)
    {
        error_log("Ftp::download_dir : " . $e->getMessage());
    }
    return $downloaded;
}
/**
 * Recursive function to download remote files
 *
 * @param ressource $cid
 * @param string $remote_dir
 * @param string $local_dir
 *
 * @return bool $download_all
 *
 */
private static function download_all($cid, $remote_dir, $local_dir)
{
    $download_all = false;
    try
    {
        if(Ftp::is_dir($remote_dir, $cid))
        {
            $files = ftp_nlist($cid, $remote_dir);
            if($files!==false)
            {
                $to_download = 0;
                $downloaded = 0;
                # do this for each file in the remote directory 
                foreach ($files as $file)
                {
                    # To prevent an infinite loop 
                    if ($file != "." && $file != "..")
                    {
                        $to_download++;
                        # do the following if it is a directory 
                        if (Ftp::is_dir($file, $cid))// $remote_dir . DIRECTORY_SEPARATOR .
                        {                                
                            # Create directory on local filesystem
                            mkdir($local_dir . DIRECTORY_SEPARATOR . basename($file));

                            # Recursive part 
                            if(Ftp::download_all($cid, $file, $local_dir . DIRECTORY_SEPARATOR . basename($file)))
                            {
                                $downloaded++;
                            }
                        }
                        else
                        { 
                            # Download files 
                            if(ftp_get($cid, $local_dir . DIRECTORY_SEPARATOR . basename($file), $file, FTP_BINARY))
                            {
                                $downloaded++;
                            }
                        } 
                    }
                }
                # Check all files and folders have been downloaded
                if($to_download===$downloaded)
                {
                    $download_all = true;
                }
            }
        }
    }
    catch(Exception $e)
    {
        error_log("Ftp::download_all : " . $e->getMessage());
    }
    return $download_all;
}

You can use the FTP functions in PHP:您可以在 PHP 中使用 FTP 函数:

http://www.php.net/manual/en/ref.ftp.php http://www.php.net/manual/en/ref.ftp.php

EDIT:编辑:

See also: PHP download entire folder (recursive) via FTP另请参阅: PHP 通过 FTP 下载整个文件夹(递归)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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