【学无止境】关于通过PHP链接FTP或SFTP的问题及解决--FTP篇
前言
前段時間在做項目的時候,接到一個需求,就是鏈接別人的FTP服務器,從別人的服務器獲取資源下載到自己的服務器上展示,我前期認真查閱了資料,其實鏈接FTP并不會太難,逼近鏈接FTP的函數PHP早有了,只是到后來給我FTP賬號時,我才發現,對方服務器是用了ssh的SFTP鏈接,這樣的話自帶的PHP函數是無法完成鏈接的,至于如何鏈接和使用,接下來就讓我們一起探究FTP和SFTP吧!
FTP
建立FTP鏈接資源
在開始使用FTP前我們要向服務器申請一個FTP的資源,就如同fopen()一樣,我們要在棧堆里面保留一個資源,這點用我們PHP自帶函數就能解決 ftp_connect()
注意:FTP函數php早有集成,不需要下載擴展了,但是你也要確保你有開擴展,請用phpinfo()驗證一下
ftp_connect(host,port,timeout)
若成功,則返回一個連接標識,否則返回 false。
| host | 必需。規定要連接的 FTP 服務器。可以是域名或 IP 地址。后面不應以斜線結尾,前面也不需要用 ftp:// 開頭。 |
| port | 可選。規定 FTP 服務器的端口。默認是21。 |
| timeout | 可選。規定該 FTP 服務器的超時時間。默認是 90 秒。 |
我們先用 ftp_connect() 申請資源。
<?php $conn = ftp_connect("ftp.testftp.com") or die("不能連接"); ?>如果成功產生資源會返回一個id,否則就檢查一下自己的地址是否寫錯,端口是否是21,22端口是SFTP連接。
資源申請到手,我們進行登錄。
注意:FTP的特性就是必須要登錄,如果只是想拿到域名一個公開權限的文件的話,建議是用文檔流來拿。
ftp_login(ftp_connection,username,password)
ftp_login() 函數登錄 FTP 服務器。
若成功則返回 true,失敗則返回 false 并發出一個警告。
| ftp_connection | 必需。規定要使用的 FTP 連接(FTP 連接的標識符)。 |
| username | 必需。規定用于登錄的用戶名。 |
| password | 必需。規定用于登錄的密碼。 |
登錄到ftp服務器
ftp_login($conn,"admin","1");至此ftp上的資源已經建立好連接,可以直接操作了。
使用FTP資源,下載,上傳,更名,刪除。
下載 ftp_get(ftp_connection,local,remote,mode,resume)
從 FTP 服務器上下載一個文件。
若成功則返回 true,失敗則返回 false。
| ftp_connection | 必需。規定要使用的 FTP 連接(FTP 連接的標識符)。 |
| local | 必需。規定本地文件。 |
| remote | 必需。規定從中進行拷貝的文件的路徑。 |
| mode | 必需。規定傳輸模式。可能的值有:FTP_ASCII(文本模式),FTP_BINARY(二進制模式) |
| resume | 必需。規定在遠程文件中的何處開始拷貝。默認是 0。 |
注意:最后這個參數是要帶上的!!
上傳 ftp_put(ftp_connection,remote,local,mode,resume)
把文件上傳到服務器。
若成功則返回 true,失敗則返回 false。
| ftp_connection | 必需。規定要使用的 FTP 連接(FTP 連接的標識符)。 |
| remote | 必需。上傳到服務器上的文件名。 |
| local | 必需。規定要上傳的本地文件的路徑。 |
| mode | 必需。規定傳輸模式。可能的值有:FTP_ASCII(文本模式),FTP_BINARY(二進制模式) |
| resume | 必需。規定在遠程文件中的何處開始拷貝。默認是 0。 |
更名 ftp_rename(ftp_connection,from,to)
更改 FTP 服務器上的文件或目錄名。
如果成功,則返回 true,否則返回 false。
| ftp_connection | 必需。規定要使用的 FTP 連接(FTP 連接的標識符)。 |
| from | 必需。規定要改名的文件或目錄。 |
| to | 必需。規定文件或目錄的新名稱。 |
注意:不管是文件或者目錄都是要帶絕對路徑的
刪除 ftp_delete(ftp_connection,path)
刪除 FTP 服務器上的一個文件。
若成功,則返回 true,否則返回 false。
| ftp_connection | 必需。規定要使用的 FTP 連接(FTP 連接的標識符)。 |
| path | 必需。規定要刪除的文件的路徑。 |
一個問題:很多同學有這樣的問題,可以從ftp軟件上打開的文件,用php就是下不下來,這個問題其實和ftp的主動被動性有關
被動模式 ftp_pasv(ftp_connection,mode)
在被動模式中,數據連接是由客戶機來初始化的,而不是服務器。這在客戶機位于防火墻之后時比較有用。
| ftp_connection | 必需。規定要使用的 FTP 連接(FTP 連接的標識符)。 |
| mode | 必需。規定模式。 |
說明:
如果參數 mode 為真,打開被動模式傳輸 (PASV MODE) ,否則,如果參數 mode 為假,則關閉被動傳輸模式。在被動模式打開的情況下,數據的傳送由客戶機啟動,而不是由服務器開始。
關于一個FTP的操作類
分享這個操作類給大家
class Ftp {private $hostname = '';private $username = '';private $password = '';private $port = 21;private $passive = TRUE;private $debug = TRUE;private $conn_id = FALSE;/*** 構造函數** @param array 配置數組 : $config = array('hostname'=>'','username'=>'','password'=>'','port'=>''...);*/public function __construct($config = array()) {if(count($config) > 0) {$this->_init($config);}}/*** FTP連接** @access public* @param array 配置數組* @return boolean*/public function connect($config = array()) {if(count($config) > 0) {$this->_init($config);}if(FALSE === ($this->conn_id = @ftp_connect($this->hostname,$this->port))) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_connect");}return FALSE;}if( ! $this->_login()) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_login");}return FALSE;}if($this->passive === TRUE) {ftp_pasv($this->conn_id, TRUE);}return TRUE;}/*** 目錄改變** @access public* @param string 目錄標識(ftp)* @param boolean* @return boolean*/public function chgdir($path = '', $supress_debug = FALSE) {if($path == '' OR ! $this->_isconn()) {return FALSE;}$result = @ftp_chdir($this->conn_id, $path);if($result === FALSE) {if($this->debug === TRUE AND $supress_debug == FALSE) {$this->_error("ftp_unable_to_chgdir:dir[".$path."]");}return FALSE;}return TRUE;}/*** 目錄生成** @access public* @param string 目錄標識(ftp)* @param int 文件權限列表* @return boolean*/public function mkdir($path = '', $permissions = NULL) {if($path == '' OR ! $this->_isconn()) {return FALSE;}$result = @ftp_mkdir($this->conn_id, $path);if($result === FALSE) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_mkdir:dir[".$path."]");}return FALSE;}if( ! is_null($permissions)) {$this->chmod($path,(int)$permissions);}return TRUE;}/*** 上傳** @access public* @param string 本地目錄標識* @param string 遠程目錄標識(ftp)* @param string 上傳模式 auto || ascii* @param int 上傳后的文件權限列表* @return boolean*/public function upload($localpath, $remotepath, $mode = 'auto', $permissions = NULL) {if( ! $this->_isconn()) {return FALSE;}if( ! file_exists($localpath)) {if($this->debug === TRUE) {$this->_error("ftp_no_source_file:".$localpath);}return FALSE;}if($mode == 'auto') {$ext = $this->_getext($localpath);$mode = $this->_settype($ext);}$mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;$result = @ftp_put($this->conn_id, $remotepath, $localpath, $mode);if($result === FALSE) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_upload:localpath[".$localpath."]/remotepath[".$remotepath."]");}return FALSE;}if( ! is_null($permissions)) {$this->chmod($remotepath,(int)$permissions);}return TRUE;}/*** 下載** @access public* @param string 遠程目錄標識(ftp)* @param string 本地目錄標識* @param string 下載模式 auto || ascii* @return boolean*/public function download($remotepath, $localpath, $mode = 'auto') {if( ! $this->_isconn()) {return FALSE;}if($mode == 'auto') {$ext = $this->_getext($remotepath);$mode = $this->_settype($ext);}$mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;$result = @ftp_get($this->conn_id, $localpath, $remotepath, $mode);if($result === FALSE) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_download:localpath[".$localpath."]-remotepath[".$remotepath."]");}return FALSE;}return TRUE;}/*** 重命名/移動** @access public* @param string 遠程目錄標識(ftp)* @param string 新目錄標識* @param boolean 判斷是重命名(FALSE)還是移動(TRUE)* @return boolean*/public function rename($oldname, $newname, $move = FALSE) {if( ! $this->_isconn()) {return FALSE;}$result = @ftp_rename($this->conn_id, $oldname, $newname);if($result === FALSE) {if($this->debug === TRUE) {$msg = ($move == FALSE) ? "ftp_unable_to_rename" : "ftp_unable_to_move";$this->_error($msg);}return FALSE;}return TRUE;}/*** 刪除文件** @access public* @param string 文件標識(ftp)* @return boolean*/public function delete_file($file) {if( ! $this->_isconn()) {return FALSE;}$result = @ftp_delete($this->conn_id, $file);if($result === FALSE) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_delete_file:file[".$file."]");}return FALSE;}return TRUE;}/*** 刪除文件夾** @access public* @param string 目錄標識(ftp)* @return boolean*/public function delete_dir($path) {if( ! $this->_isconn()) {return FALSE;}//對目錄宏的'/'字符添加反斜杠'\'$path = preg_replace("/(.+?)\/*$/", "\\1/", $path);//獲取目錄文件列表$filelist = $this->filelist($path);if($filelist !== FALSE AND count($filelist) > 0) {foreach($filelist as $item) {//如果我們無法刪除,那么就可能是一個文件夾//所以我們遞歸調用delete_dir()if( ! @delete_file($item)) {$this->delete_dir($item);}}}//刪除文件夾(空文件夾)$result = @ftp_rmdir($this->conn_id, $path);if($result === FALSE) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_delete_dir:dir[".$path."]");}return FALSE;}return TRUE;}/*** 修改文件權限** @access public* @param string 目錄標識(ftp)* @return boolean*/public function chmod($path, $perm) {if( ! $this->_isconn()) {return FALSE;}//只有在PHP5中才定義了修改權限的函數(ftp)if( ! function_exists('ftp_chmod')) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_chmod(function)");}return FALSE;}$result = @ftp_chmod($this->conn_id, $perm, $path);if($result === FALSE) {if($this->debug === TRUE) {$this->_error("ftp_unable_to_chmod:path[".$path."]-chmod[".$perm."]");}return FALSE;}return TRUE;}/*** 獲取目錄文件列表** @access public* @param string 目錄標識(ftp)* @return array*/public function filelist($path = '.') {if( ! $this->_isconn()) {return FALSE;}return ftp_nlist($this->conn_id, $path);}/*** 關閉FTP** @access public* @return boolean*/public function close() {if( ! $this->_isconn()) {return FALSE;}return @ftp_close($this->conn_id);}/*** FTP成員變量初始化** @access private* @param array 配置數組* @return void*/private function _init($config = array()) {foreach($config as $key => $val) {if(isset($this->$key)) {$this->$key = $val;}}//特殊字符過濾$this->hostname = preg_replace('|.+?://|','',$this->hostname);}/*** FTP登陸** @access private* @return boolean*/private function _login() {return @ftp_login($this->conn_id, $this->username, $this->password);}/*** 判斷con_id** @access private* @return boolean*/private function _isconn() {if( ! is_resource($this->conn_id)) {if($this->debug === TRUE) {$this->_error("ftp_no_connection");}return FALSE;}return TRUE;}/*** 從文件名中獲取后綴擴展** @access private* @param string 目錄標識* @return string*/private function _getext($filename) {if(FALSE === strpos($filename, '.')) {return 'txt';}$extarr = explode('.', $filename);return end($extarr);}/*** 從后綴擴展定義FTP傳輸模式 ascii 或 binary** @access private* @param string 后綴擴展* @return string*/private function _settype($ext) {$text_type = array ('txt','text','php','phps','php4','js','css','htm','html','phtml','shtml','log','xml');return (in_array($ext, $text_type)) ? 'ascii' : 'binary';}/*** 錯誤日志記錄** @access prvate* @return boolean*/private function _error($msg) {return @file_put_contents('ftp_err.log', "date[".date("Y-m-d H:i:s")."]-hostname[".$this->hostname."]-username[".$this->username."]-password[".$this->password."]-msg[".$msg."]\n", FILE_APPEND);} }可以加1577452412 一起討論
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的【学无止境】关于通过PHP链接FTP或SFTP的问题及解决--FTP篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【坑爹微信】微信支付相关问题解决
- 下一篇: Git简单使用笔记