【问题标题】:Upload Entire Directory via PHP FTP通过 PHP FTP 上传整个目录
【发布时间】:2010-10-29 23:10:47
【问题描述】:

我正在尝试编写一个脚本,它将存储在我的服务器上的目录的全部内容通过 ftp 上传到其他服务器。

我一直在阅读documentation on www.php.net,但似乎找不到一次上传多个文件的方法。

有没有办法做到这一点,或者是否有脚本可以索引该目录并创建要上传的文件数组?

提前感谢您的帮助!

【问题讨论】:

    标签: php upload ftp directory


    【解决方案1】:

    打开连接后,串行上传目录的内容很简单:

    foreach (glob("/directory/to/upload/*.*") as $filename)
        ftp_put($ftp_stream, basename($filename) , $filename, FTP_BINARY);
    

    并行上传所有文件会更困难。

    【讨论】:

      【解决方案2】:

      所以,我采用了@iYETER 的代码,并将其包装为一个类对象。

      您可以通过以下几行调用此代码:

      $ftp = new FtpNew("hostname");
      
      $ftpSession = $ftp->login("username", "password");
      
      if (!$ftpSession) die("Failed to connect.");
      
      $errorList = $ftp->send_recursive_directory("/local/dir/", "/remote/dir/");
      print_r($errorList);
      
      $ftp->disconnect();
      

      它递归地爬取本地目录,并将其放在远程目录相对。如果遇到任何错误,它会为每个文件及其异常代码创建一个数组层次结构(目前我只捕获了 2 个,如果是另一个错误,它现在会抛出默认路由)

      这个包裹到的类:

      <?php
      //Thanks for iYETER on http://stackoverflow.com/questions/927341/upload-entire-directory-via-php-ftp
      
      class FtpNew {
      private $connectionID;
      private $ftpSession = false;
      private $blackList = array('.', '..', 'Thumbs.db');
      public function __construct($ftpHost = "") {
          if ($ftpHost != "") $this->connectionID = ftp_connect($ftpHost);
      }
      
      public function __destruct() {
          $this->disconnect();
      }
      
      public function connect($ftpHost) {     
          $this->disconnect();
          $this->connectionID = ftp_connect($ftpHost);
          return $this->connectionID;
      }
      
      public function login($ftpUser, $ftpPass) {
          if (!$this->connectionID) throw new Exception("Connection not established.", -1);
          $this->ftpSession = ftp_login($this->connectionID, $ftpUser, $ftpPass);
          return $this->ftpSession;
      }
      
      public function disconnect() {
          if (isset($this->connectionID)) {
              ftp_close($this->connectionID);
              unset($this->connectionID);
          }
      }
      
      public function send_recursive_directory($localPath, $remotePath) {
          return $this->recurse_directory($localPath, $localPath, $remotePath);
      }
      
      private function recurse_directory($rootPath, $localPath, $remotePath) {
          $errorList = array();
          if (!is_dir($localPath)) throw new Exception("Invalid directory: $localPath");
          chdir($localPath);
          $directory = opendir(".");
          while ($file = readdir($directory)) {
              if (in_array($file, $this->blackList)) continue;
              if (is_dir($file)) {
                  $errorList["$remotePath/$file"] = $this->make_directory("$remotePath/$file");
                  $errorList[] = $this->recurse_directory($rootPath, "$localPath/$file", "$remotePath/$file");
                  chdir($localPath);
              } else {
                  $errorList["$remotePath/$file"] = $this->put_file("$localPath/$file", "$remotePath/$file");
              }
          }
          return $errorList;
      }
      
      public function make_directory($remotePath) {
          $error = "";
          try {
              ftp_mkdir($this->connectionID, $remotePath);
          } catch (Exception $e) {
              if ($e->getCode() == 2) $error = $e->getMessage(); 
          }
          return $error;
      }
      
      public function put_file($localPath, $remotePath) {
          $error = "";
          try {
              ftp_put($this->connectionID, $remotePath, $localPath, FTP_BINARY); 
          } catch (Exception $e) {
              if ($e->getCode() == 2) $error = $e->getMessage(); 
          }
          return $error;
      }
      }
      

      【讨论】:

        【解决方案3】:

        循环执行,遍历文件夹中的所有文件

        $servername = $GLOBALS["servername"];
            $ftpUser = $GLOBALS["ftpUser"];
            $ftpPass = $GLOBALS["ftpPass"];
        $conn_id = ftp_connect($servername) or die("<p style=\"color:red\">Error connecting to $servername </p>");
        
        if(ftp_login($conn_id, $ftpUser, $ftpPass))
        {
            $dir_handle = @opendir($path) or die("Error opening $path");
        
                 while ($file = readdir($dir_handle)) {
                    ftp_put($conn_id, PATH_TO_REMOTE_FILE, $file)
                }
        }
        

        【讨论】:

          【解决方案4】:

          我编写了代码,脚本上传了整个文件夹及其子文件夹和文件。

          希望对你有帮助。

          <?php 
          ob_start(); 
          set_time_limit(0); 
          //r10.net fatal
          
          $anadizin="uploadedeceginizdizin"; //this is the folder that you want to upload with all subfolder and files of it.
          
          $ftpsunucu="domain.com"; //ftp domain name
          $ftpusername="ftpuser";  //ftp user name 
          $ftppass="ftppass"; //ftp passowrd
          $ftpdizin="/public_html"; //ftp main folder
          
          
          
          
          
          $arkadaslarlabardaydik = ftp_connect($ftpsunucu); 
          $ictikguldukeglendik = ftp_login($arkadaslarlabardaydik, $ftpusername, $ftppass); 
          
          if((!$arkadaslarlabardaydik) || (!$ictikguldukeglendik))  
          { 
            echo "cant connect!"; 
            die(); 
          } 
          
          
          function klasoruoku($dizinadi) 
          { 
            global $nerdeyiz,$fulldizin,$ftpdizin,$arkadaslarlabardaydik,$ftpdizin; 
          
            chdir($dizinadi."\\"); 
            $dizin = opendir("."); 
          
            while($bilgi=readdir($dizin))  
            { 
              if ($bilgi!='.' and $bilgi!='..' and $bilgi!="Thumbs.db") 
              {  
                  $tamyol="$dizinadi\\$bilgi"; 
          
                  $lokalkla=str_replace("".$nerdeyiz."\\","",$dizinadi).""; 
                  $lokaldosya="$lokalkla\\$bilgi"; 
                  $ftpyeyolla=str_replace(array("\\\\","\\"),array("/","/"),"$ftpdizin\\".str_replace("".$fulldizin."","",$dizinadi)."\\$bilgi"); 
          
                  if(!is_dir($bilgi)) 
                  { 
                    $yükleme = ftp_put($arkadaslarlabardaydik, $ftpyeyolla, $tamyol, FTP_BINARY); 
          
                    if (!$yükleme)  
                    { 
                        echo "$lokaldosya <font color=red>uploaded</font>"; echo "<br>";  fls(); 
                    }  
                    else  
                    { 
                        echo "$lokaldosya <font color=green>not uploaded</font>"; echo "<br>"; fls(); 
                    } 
                  } 
                  else 
                  {  
                    ftp_mkdir($arkadaslarlabardaydik, $ftpyeyolla); 
                    klasoruoku("$dizinadi\\$bilgi"); 
                    chdir($dizinadi."\\"); 
                    fls(); 
                  } 
              } 
            } 
            closedir ($dizin); 
          } 
          
          function fls() 
          { 
              ob_end_flush(); 
              ob_flush(); 
              flush(); 
              ob_start(); 
          } 
          
          $nerdeyiz=getcwd(); 
          $fulldizin=$nerdeyiz."\\$anadizin"; 
          klasoruoku($fulldizin); 
          ftp_close($arkadaslarlabardaydik); 
          
          ?>
          

          【讨论】:

          • 我希望变量是用英文写的:(无论如何我都赞成你
          【解决方案5】:

          如果您想一次上传多个文件,则需要使用 thread 或 fork。

          我不确定 PHP 中的线程实现,但您应该看看 PHP SPL 和/或 PEAR

          编辑:感谢 Frank Farmer 让我知道 PHP 中有一个 fork() 函数,称为 pcntl_fork()

          您还必须递归获取整个内容目录才能上传给定目录的所有文件。

          【讨论】:

          • PHP 没有线程,但它会 fork(使用 pcntl_fork()),并且 PHP 的 fork 功能有一些类似线程的包装器。
          • 我不建议使用分叉。那是毛茸茸的东西。简单地打开多个连接并使用 socket_select() 异步写入要容易得多。
          猜你喜欢
          • 1970-01-01
          • 2012-10-21
          • 1970-01-01
          • 1970-01-01
          • 2012-10-30
          • 2011-04-29
          • 1970-01-01
          • 1970-01-01
          • 2015-06-20
          相关资源
          最近更新 更多