XLI. FTP 函数

简介

FTP 函数可以帮助实现客户机与服务器之间标准文件传送协议(FTP)的规范进行文件传送。FTP 的详细定义参见 http://www.faqs.org/rfcs/rfc959。此扩展库用来使运行的脚本对 FTP 服务器进行广泛的控制。如果只想在一个 FTP 服务器上读写文件,考虑使用文件系统函数中的 ftp:// wrapper,它提供了简单和更直观的接口。

需求

要编译本扩展模块不需要外部库文件。

安装

In order to use FTP functions with your PHP configuration, you should add the --enable-ftp option when installing PHP 4 or greater or --with-ftp when using PHP 3.

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

在 FTP 模块中使用了一种资源类型,该资源类型为 FTP 的连接句柄,由函数 ftp_connect()ftp_ssl_connect() 产生。

预定义常量

以下常量由本扩展模块定义,因此只有在本扩展模块被编译到 PHP 中,或者在运行时被动态加载后才有效。

FTP_ASCII (integer)

FTP_TEXT (integer)

FTP_BINARY (integer)

FTP_IMAGE (integer)

FTP_TIMEOUT_SEC (integer)

参考函数 ftp_set_option()

下列变量在 PHP 4.3.0 以后版本中被加入。

FTP_AUTOSEEK (integer)

参考函数 ftp_set_option()

FTP_AUTORESUME (integer)

为 GET 和 PUT 请求自动决定恢复和开始的位置 (只能工作在 FTP_AUTOSEEK 打开的情况下)

FTP_FAILED (integer)

异步传输失败

FTP_FINISHED (integer)

异步传输成功

FTP_MOREDATA (integer)

异步传输是活动状态的

范例

例子 1. FTP 例子

<?php
// set up basic connection
$conn_id = ftp_connect($ftp_server);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// check connection
if ((!$conn_id) || (!$login_result)) {
        echo
"FTP connection has failed!";
        echo
"Attempted to connect to $ftp_server for user $ftp_user_name";
        exit;
    } else {
        echo
"Connected to $ftp_server, for user $ftp_user_name";
    }

// upload the file
$upload = ftp_put($conn_id, $destination_file, $source_file, FTP_BINARY);

// check upload status
if (!$upload) {
        echo
"FTP upload has failed!";
    } else {
        echo
"Uploaded $source_file to $ftp_server as $destination_file";
    }

// close the FTP stream
ftp_close($conn_id);
?>

目录
ftp_alloc -- Allocates space for a file to be uploaded
ftp_cdup -- 切换到当前目录的父目录
ftp_chdir -- 在 FTP 服务器上切换当前目录
ftp_chmod -- Set permissions on a file via FTP
ftp_close -- 关闭一个活动的 FTP 连接
ftp_connect -- 建立一个新的 FTP 连接
ftp_delete -- 删除 FTP 服务器上的一个文件
ftp_exec -- 请求运行一条 FTP 命令
ftp_fget -- 从 FTP 服务器上下载一个文件并保存到本地一个已经打开的文件中
ftp_fput -- 上传一个已经打开的文件到 FTP 服务器
ftp_get_option -- 返回当前 FTP 连接的各种不同的选项设置
ftp_get -- 从 FTP 服务器上下载一个文件
ftp_login -- 登录 FTP 服务器
ftp_mdtm -- 返回指定文件的最后修改时间
ftp_mkdir -- 建立新目录
ftp_nb_continue -- 连续获取/发送文件(non-blocking)
ftp_nb_fget -- Retrieves a file from the FTP server and writes it to an open file (non-blocking)
ftp_nb_fput -- Stores a file from an open file to the FTP server (non-blocking)
ftp_nb_get -- 从 FTP 服务器上获取文件并写入本地文件(non-blocking)
ftp_nb_put -- 存储一个文件至 FTP 服务器(non-blocking)
ftp_nlist -- 返回给定目录的文件列表
ftp_pasv -- 返回当前 FTP 被动模式是否打开
ftp_put -- 上传文件到 FTP 服务器
ftp_pwd -- 返回当前目录名
ftp_quit -- ftp_close() 的别名
ftp_raw -- Sends an arbitrary command to an FTP server
ftp_rawlist -- 返回指定目录下文件的详细列表
ftp_rename -- 更改 FTP 服务器上指定的文件名
ftp_rmdir -- 删除一个目录
ftp_set_option -- 设置各种 FTP 运行时选项
ftp_site -- 向服务器发送 SITE 命令
ftp_size -- 返回指定文件的大小
ftp_ssl_connect -- Opens an Secure SSL-FTP connection
ftp_systype -- 返回远程 FTP 服务器的系统类型

add a note add a note User Contributed Notes
cgray at premierconsulting dot com (Chris Gray)
24-Oct-2006 11:58
After looking everywhere for a "FULLY WORKING" ftp uploader script, I finally came up with this, by using a lot of various ones I found on the web. If you find a better way of doing something, please let me know. Thanks, and Enjoy

<?php
 
if(isset($_POST['SubmitFile'])){
    
$myFile = $_FILES['txt_file']; // This will make an array out of the file information that was stored.
    
$file = $myFile['tmp_name'];  //Converts the array into a new string containing the path name on the server where your file is.
 
    
$myFileName = basename($_POST['txt_fileName']); //Retrieve filename out of file path

    
$destination_file = "/".$myFileName//where you want to throw the file on the webserver (relative to your login dir)

     // connection settings
    
$ftp_server = "127.0.0.1"//address of ftp server.
    
$ftp_user_name = "Your UserName"; // Username
    
$ftp_user_pass = "Your Password"// Password

    
$conn_id = ftp_connect($ftp_server);        // set up basic connection
    
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass) or die("<h2>You do not have access to this ftp server!</h2>");  // login with username and password, or give invalid user message
    
if ((!$conn_id) || (!$login_result)) {  // check connection
             // wont ever hit this, b/c of the die call on ftp_login
            
echo "FTP connection has failed! <br />";
             echo
"Attempted to connect to $ftp_server for user $ftp_user_name";
             exit;
         } else {
        
//    echo "Connected to $ftp_server, for user $ftp_user_name <br />";
    
}

    
$upload = ftp_put($conn_id, $destination_file, $file, FTP_BINARY);  // upload the file
    
if (!$upload) {  // check upload status
        
echo "<h2>FTP upload of $myFileName has failed!</h2> <br />";
     } else {
         echo
"Uploading $myFileName Complete!<br /><br />";
     }

    
ftp_close($conn_id); // close the FTP stream
 
}
?>

<html>
  <head>

  </head>
  <body>
       <form enctype="multipart/form-data" action="<?php echo $_SERVER['PHP_SELF'];?>" method="POST">
           Please choose a file: <input name="txt_file" type="file" id="txt_file" tabindex="1" size="35" onChange="txt_fileName.value=txt_file.value" />
           <input name="txt_fileName" type="hidden" id="txt_fileName" tabindex="99" size="1" />

           <input type="submit" name="SubmitFile" value="Upload File" accesskey="ENTER" tabindex="2" />
     </form>
  </body>
<html>
nicklas at programmera dot nu
16-Aug-2006 05:56
I didn't quite like my FTP program since I had to make all the settings all over when i restarted the client, so I made this script for simple ftp uploading, its running as a CLI app.

<?php

  
//if STDIN isn't defined, define it
  
if (!defined("STDIN"))
   {
  
      
define("STDIN", fopen("php://stdin", "r"));
      
   }
  
   echo
"FTP file uploader\r\n\r\n";

   echo
"Server: ";

  
//trim() all the fgets cause it seams to add a \n
  
$server = trim(fgets(STDIN));
  
   echo
"Username: ";
  
  
$username = trim(fgets(STDIN));
  
   echo
"Password: ";
  
  
$password = trim(fgets(STDIN));
  
  
$connect = ftp_connect($server);
  
$login = ftp_login($connect, $username, $password);
  
   if ((!
$connect) || (!$login))
   {
  
       exit(
"Login failed.\r\n");
      
   }
  
   echo
"Connected\r\n";

   echo
"PASV (Y/Any key = Off): ";
  
   if(
trim(fgets(STDIN)) == "Y")
   {

      
//enable passive mode
      
ftp_pasv($connect, true);
  
           echo
"PASV: On\r\n";
      
   }
   else
   {
  
       echo
"PASV: Off\r\n";

   }

  
$showContent = ftp_nlist($connect, "");
  
   echo
"Listing Contents:\r\n";
      
      
var_dump($showContent);

   echo
"File to upload: ";
  
  
$file = trim(fgets(STDIN));
  
  
//escape the uploading process by typing "exit;"
  
if ($file == "exit;")
   {
  
       exit;
  
   }
  
  
//use "$file, $file" since the file shouldn't be renamed, also if its a binary file change the last argument to FTP_BINARY
  
$upload = ftp_put($connect, $file, $file, FTP_ASCII);
  
   if (!
$upload)
   {
  
       exit(
"Upload failed.\r\n");
      
   }
   else
   {
  
       echo
"The file \"" . $file . "\" was successfully uploaded. :)\r\nSize of \"" . $file . "\": " . filesize($file) / 1024 ."kb.\r\n";
       echo
"My work is done, bye.\r\n";
      
   }
  
  
ftp_close($connect);

?>
magic2lantern at mail dot ru
24-Dec-2005 12:19
This is a simple script writen by me which allows the user
run it in console and get tree from FTP Server.

<?php
$argv
= $_SERVER["argv"];
$argv = array_slice($argv,1);
if (
getenv("HTTP_HOST")) {exit("For bash execution only!");}
if ((empty(
$argv[0])) || (empty($argv[1]))) {exit("Usage: thisscript.php 10.0.0.10 /games/Arcade/
where 10.0.0.10 is the FTP Server and /games/Arcade is the start path on FTP\n"
);}

// connect to the ftp server
$connect_id = ftp_connect($argv[0]);
// login on the server
if ($connect_id) { $login_result = ftp_login($connect_id, 'anonymous', 'JustForFun'); }
// check connection
if ((!$connect_id) || (!$login_result)) {
   echo
"Unable to connect the remote FTP Server!\n";
   exit;
}
function
ftp_get_dir ($ftp_dir) {
global
$connect_id;
$ftp_contents = ftp_nlist ($connect_id, $ftp_dir);
   for (
$myCounter_for_server_elements = 0; !empty ($ftp_contents[$myCounter_for_server_elements]);
$myCounter_for_server_elements++)
   {
// get elements list in current dir
      
echo $argv[0] . $ftp_dir . $ftp_contents[$myCounter_for_server_elements] . "\n";
      
ftp_get_dir ($ftp_dir . $ftp_contents[$myCounter_for_server_elements] . '/');
   }
}
ftp_get_dir ($argv[1]);
// close connection
ftp_close($connect_id);
?>
leonardo at rol dot com dot ro
09-Aug-2005 09:51
Here is an example for downloading a remote ftp structure to local server, useful for migrating sites from one server to another, especially when you are upgrading ensim ;)

http://leonardo.rol.ro/ftpleech.txt
dickiedyce at uk dot com
07-May-2005 11:20
It may seem obvious to others, but it had me stumped for nearly an hour! If you can connect to an ftp site but some functions (list, put, get etc) don't work, then try using ftp_pasv and set passive mode on.

<?php

// setup $host and $file variables for your setup before here...

$hostip = gethostbyname($host);
$conn_id = ftp_connect($hostip);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// IMPORTANT!!! turn passive mode on
ftp_pasv ( $conn_id, true );

if ((!
$conn_id) || (!$login_result)) {
  echo
"FTP connection has failed!";
  echo
"Attempted to connect to $host for user $ftp_user_name";
  die;
} else {
  echo
"Connected to $host, for user $ftp_user_name<br>";
  echo
"Host IP is $hostip<br>";
 
 
// upload a file
 
if (ftp_put($conn_id, $remote_file, $file, FTP_ASCII)) {
   echo
"successfully uploaded $file<br>";
  } else {
   echo
"There was a problem while uploading $file<br>";
  }
  
 
// close the connection
 
ftp_close($conn_id);
}
?>
arjen at queek dot nl
15-Jul-2004 10:38
If you prefer a OO-approach to the FTP-functions, you can use this snippet of code (PHP5 only! and does add some overhead). It's just a "start-up", extend/improve as you wish...
You can pass all ftp_* functions to your object and stripping ftp_ of the function name. Plus, you don't have to pass the ftp-resource as the first argument.

For example:
<?php
ftp_delete
($ftp, $file);    // Where $ftp is your ftp-resource
?>

Can become:
<?php
$ftp
->delete($file);        // Where $ftp is your FTP-object
?>

Code:
<?php

class FTP {

  
private $ftp;
  
  
/* public Void __construct(): Constructor */
  
public function __construct($host, $port = 21, $timeout = 90) {
      
$this->ftp = ftp_connect($host, $port, $timeout);
   }
  
  
/* public Void __destruct(): Destructor */
  
public function __destruct() {
       @
ftp_close($this->ftp);
   }

  
/* public Mixed __call(): Re-route all function calls to the PHP-functions */
  
public function __call($function, $arguments) {
      
// Prepend the ftp resource to the arguments array
      
array_unshift($arguments, $this->ftp);
      
      
// Call the PHP function
      
return call_user_func_array('ftp_' . $function, $arguments);
   }
  
}

?>
Kristy Christie (kristy at isp7 dot net)
16-Jun-2004 02:50
Here's a little function that I created to recurse through a local directory and upload the entire contents to a remote FTP server.

In the example, I'm trying to copy the entire "iwm" directory located at /home/kristy/scripts/iwm to a remote server's /public_html/test/ via FTP.

The only trouble is that for the line "if (!ftp_chdir($ftpc,$ftproot.$srcrela))", which I use to check if the directory already exists on the remote server, spits out a warning about being unable to change to that directory if it doesn't exist.

But an error handler should take care of it.

My thanks to the person who posted the snippet on retrieving the list of files in a directory.

For the version of the script that echo's it's progress as it recurses & uploads, go to: http://pastebin.com/73784

<?php

// --------------------------------------------------------------------
// THE TRIGGER
// --------------------------------------------------------------------

   // set the various variables
  
$ftproot = "/public_html/test/";
  
$srcroot = "/home/kristy/scripts/";       
  
$srcrela = "iwm/";

  
// connect to the destination FTP & enter appropriate directories both locally and remotely
  
$ftpc = ftp_connect("ftp.mydomain.com");
  
$ftpr = ftp_login($ftpc,"username","password");

   if ((!
$ftpc) || (!$ftpr)) { echo "FTP connection not established!"; die(); }
   if (!
chdir($srcroot)) { echo "Could not enter local source root directory."; die(); }
   if (!
ftp_chdir($ftpc,$ftproot)) { echo "Could not enter FTP root directory."; die(); }

  
// start ftp'ing over the directory recursively
  
ftpRec ($srcrela);

  
// close the FTP connection
  
ftp_close($ftpc);

// --------------------------------------------------------------------
// THE ACTUAL FUNCTION
// --------------------------------------------------------------------
function ftpRec ($srcrela)
{
   global
$srcroot;
   global
$ftproot;
   global
$ftpc;
   global
$ftpr;
              
  
// enter the local directory to be recursed through
  
chdir($srcroot.$srcrela);
  
  
// check if the directory exists & change to it on the destination
  
if (!ftp_chdir($ftpc,$ftproot.$srcrela))
   {
      
// remote directory doesn't exist so create & enter it
          
ftp_mkdir    ($ftpc,$ftproot.$srcrela);
          
ftp_chdir    ($ftpc,$ftproot.$srcrela);
   }

   if (
$handle = opendir("."))
   {
       while (
false !== ($fil = readdir($handle)))
       {
           if (
$fil != "." && $fil != "..")   
           {
              
// check if it's a file or directory
              
if (!is_dir($fil))
               {   
                  
// it's a file so upload it
                  
ftp_put($ftpc, $ftproot.$srcrela.$fil, $fil, FTP_BINARY);
               }
               else
               {
                  
// it's a directory so recurse through it
                  
if ($fil == "templates")
                   {
                          
// I want the script to ignore any directories named "templates"
                           // and therefore, not recurse through them and upload their contents
                  
}
                   else
                   {
                      
ftpRec ($srcrela.$fil."/");
                      
chdir ("../");
                   }
               }
         }
     }
    
closedir($handle);
   }   
}
?>
postmaster at alishomepage dot com
24-Jan-2004 07:29
I have written an OpenSource ZIP2FTP interface, which actually takes a given ZIP file and decompresses it in the folder on an FTP server you specify...

Therefore it may be quite interesting for you people interested in FTP, its adress is http://zip2ftp.alishomepage.com ; those who directly want the source may visit http://zip2ftp.alishomepage.com/?do=getSource
Vikrant Korde <vakorde at hotmail dot com>
14-Nov-2003 09:35
<?

//If you want to move or replicate the folder hierarchy from your current server to another remote server. Then this will be helpful as this will browse the current server's directory and at the same time it will copy that file in the remote server in the same directory.

//This script will copy all the files from this directory and subdirectory to another remote server via FTP

function rec_copy ($source_path, $destination_path, $con)
{
  
ftp_mkdir($con, $destination_path);
  
ftp_site($con, 'CHMOD 0777 '.$destination_path);
  
ftp_chdir($con,$destination_path);

   if (
is_dir($source_path))
   {
      
chdir($source_path);
      
$handle=opendir('.');
       while ((
$file = readdir($handle))!==false)
       {
           if ((
$file != ".") && ($file != ".."))
           {
               if (
is_dir($file))
               {
                  
// here i am restricting the folder name 'propertyimages' from being copied to remote server. -- VK
                  
if($file != "propertyimages")
                   {
                      
rec_copy ($source_path."/".$file, $file, $con);
                      
chdir($source_path);
                      
ftp_cdup($con);
                   }
               }
               if (
is_file($file))
               {
                  
$fp = fopen($file,"r");
                  
// this will convert spaces to '_' so that it will not throw error.  -- VK
                  
ftp_fput ($con, str_replace(" ", "_", $file), $fp,FTP_BINARY);
                  
ftp_site($con, 'CHMOD 0755 '.str_replace(" ", "_", $file));
               }
           }
       }
      
closedir($handle);
   }
}

// make a FTP connection --VK
$con = ftp_connect("69.18.213.131",21);
$login_result = ftp_login($con,"username","password");   

// this is the root path for the remote server-- VK
$rootpath = "mainwebsite_html";   

// this is the physical path of the source directory. actually u can also use the relative path. -- VK
$sourcepath = realpath("../")."/resdesk";

// this directory name will only change the top most directory and not the inner one -- VK
$destination_dir_name = "resdesk_".$account_id."/";

rec_copy ($sourcepath, $destination_dir_name, $con);
if (
function_exists("ftp_close"))
{
  
ftp_close($con);
}
?>
postmaster at alishomepage dot com
24-Oct-2003 07:06
Here's another FTP interface over PHP (also uses MySQL)

http://myftp.alishomepage.com

PS: this script will ALSO allow you to download its source... So it becomes interesting for YOU PROGRAMMERS as well :D
arjenjb dot wanadoo dot nl
10-Mar-2003 02:29
Check http://nanoftpd.sourceforge.net/ for a FTP server written in PHP.
Supports Passive and Active FTP, and all other standard FTP commands as decribed in RFC959.
NOSPAMkent at ioflux dot NOSPAM dot com
20-Sep-2002 08:05
I think what some other posts were trying to say which may need clarification is that in PHP 4.2.3, ftp_connect("myhost.com") was failing most of the time, except it would work like every few minutes.

The fix is that ftp_connect seems to have a bug resolving addresses. If you do:

$hostip = gethostbyname($host);
$conn_id = ftp_connect($hostip);

It seems to solve the problem.
(Other users referred to an ftpbuf() error... not sure what that is, but this should fix it.)
sven at cartell-network dot de
14-Feb-2002 03:27
connection to a ftp server across proxy

$ftp_server = "proxy"; f.e. 123.456.789.10
$ftp_user_name = "username@ftpserver"; f.e. exampleuk@www.example.uk
$ftp_user_pass = "password";

$conn_id = ftp_connect($ftp_server, 2121);
$login_result = ftp_login( $conn_id, $ftp_user_name, $ftp_user_pass );