php实现通过ftp上传文件

在php中我们可以利用ftp_connect相关函数实现文件上传与下载功能,其实就是ftp客户端一样的操作,下面我来给大家介绍如何利用php来实现

大概原理

遍历项目中的所有非排除文件,然后获取 文件修改时间晚于文件上一次修改时间 的文件

然后将这些文件,通过ftp上传到对应的目录

具体代码如下:

因为只是工具,代码很乱,见谅

  1. <?php
  2. error_reporting(7);
  3. if ($_SERVER['SERVER_ADDR'])exit;//禁止在web服务器下运行
  4. $_GET['exclude'] = array('number.txt','uploads','Zend','docs','cache','You','managesdk'); //排除上传目录,定义为全局变量
  5. $fileobj = new FilerFile();
  6. $path = "/data/longtu/"; //项目目录的根目录
  7. $files = $fileobj->Zip($path); //过滤出最新的修改文件
  8. $path = str_replace("/data/longtu/","",$path);
  9. $config = array(
  10. 'hostname' => 'xxx.xxx.xx.xxx', //ftp服务器 地址
  11. 'username' => 'xxx', //ftp用户
  12. 'password' => '?xxxxxxxxxxx', //ftp密码
  13. 'port' => 21 //端口
  14. );
  15. $ftp = new Ftp();
  16. $ftp->connect($config); //链接服务器
  17. //$a=$ftp->filelist();
  18. $LOCAL_ROOT = realpath(dirname(__DIR__)."/../../");
  19. chdir($LOCAL_ROOT);
  20. foreach ($files as $k=>$v){
  21. $f = $path.$v;
  22. $tmp = $ftp->upload($f, $f);
  23. if($tmp){
  24. echo "upload $f -> success \n";
  25. }
  26. }
  27. //$ftp->download('ftp_upload.log','ftp_download.log');
  28. //
  29. //$ftp->upload('ftp_err.log','ftp_upload.log');
  30. //$ftp->download('ftp_upload.log','ftp_download.log');
  31. /*
  32. *
  33. *
  34. * $dir = "/test";
  35. if(@ftp_chdir($conn, $dir))
  36. 判断是否为文件夹
  37. * Enter description here ...
  38. * @author Administrator
  39. *
  40. */
  41. class FilerFile
  42. {
  43. var $time_path;
  44. private $fctimes = array();
  45. function Zip($dir)
  46. {
  47. $this->time_path = rtrim($dir,"/")."/.~~~time.php";
  48. //@unlink($this->time_path);
  49. $filelist = $this -> GetFileList($dir);
  50. file_put_contents($this->time_path,"<?php \n return ".var_export($this->fctimes,true).";");
  51. return $filelist;
  52. }
  53. function appendFilectime($file)
  54. {
  55. $time_file_path = $this->time_path;
  56. $ftime = @include($time_file_path);
  57. $ftime = $ftime ? $ftime : array();
  58. $time = filectime($file);
  59. if(!file_exists($time_file_path))file_put_contents($time_file_path,"<?php \n");
  60. }
  61. function getFileByFilectime($file)
  62. {
  63. static $time_data ;
  64. $time_file_path = $this->time_path;
  65. if (!$time_data){
  66. $time_data= @include_once($time_file_path);
  67. }
  68. $time_data = $time_data ? $time_data : array();
  69. //var_dump($file,$time_data[$file] == filectime($file));
  70. //echo $file."\t".$time_data[$file]."\n";
  71. if ($time_data[$file] == filemtime($file)){
  72. return false;
  73. }else{
  74. return $file;
  75. }
  76. }
  77. function GetFileList($dir,$path="")
  78. {
  79. static $tmpp = "";
  80. if ($path=="" && !$tmpp){
  81. $tmpp = $dir;
  82. }
  83. $d = dir($dir);
  84. $files = array();
  85. if ($d)
  86. {
  87. $pathP=str_replace($tmpp,"",$dir);
  88. $pathP=str_replace(array("\\\\","/"),DIRECTORY_SEPARATOR,$pathP);
  89. $pathP=str_replace(DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR,DIRECTORY_SEPARATOR,$pathP);
  90. while($f = $d->read())
  91. {
  92. if ($f == '.' || $f=='..' || $f{0}=='.' || $f=='Zend' || in_array($f, $_GET['exclude']))continue;
  93. $newdir = rtrim($dir,"/")."/".$f;
  94. if (is_dir($newdir)){
  95. $files = array_merge($files,$this->GetFileList($newdir,$newdir));
  96. }else{
  97. $abspath_file = (rtrim($dir,"/") ? rtrim($dir,"/")."/" : "").$f;
  98. $this->fctimes[$abspath_file] = filemtime($abspath_file);
  99. if (!$this->getFileByFilectime($abspath_file))continue;
  100. $file = (rtrim($pathP,"/") ? rtrim($pathP,"/")."/" : "").$f;
  101. $files[] = $file;
  102. }
  103. }
  104. }
  105. return $files;
  106. }
  107. }
  108. /**
  109. * 仿写CodeIgniter的FTP类
  110. * FTP基本操作:
  111. * 1) 登陆; connect
  112. * 2) 当前目录文件列表; filelist
  113. * 3) 目录改变; chgdir
  114. * 4) 重命名/移动; rename
  115. * 5) 创建文件夹; mkdir
  116. * 6) 删除; delete_dir/delete_file
  117. * 7) 上传; upload
  118. * 8) 下载 download
  119. *
  120. * @author quanshuidingdang
  121. */
  122. class Ftp {
  123. private $hostname = '';
  124. private $username = '';
  125. private $password = '';
  126. private $port = 21;
  127. private $passive = TRUE;
  128. private $debug = TRUE;
  129. private $conn_id = FALSE;
  130. /**
  131. * 构造函数
  132. *
  133. * @param array 配置数组 : $config = array('hostname'=>'','username'=>'','password'=>'','port'=>''...);
  134. */
  135. public function __construct($config = array()) {
  136. if(count($config) > 0) {
  137. $this->_init($config);
  138. }
  139. }
  140. /**
  141. * FTP连接
  142. *
  143. * @access public
  144. * @param array 配置数组
  145. * @return boolean
  146. */
  147. public function connect($config = array()) {
  148. if(count($config) > 0) {
  149. $this->_init($config);
  150. }
  151. if(FALSE === ($this->conn_id = @ftp_connect($this->hostname,$this->port))) {
  152. if($this->debug === TRUE) {
  153. $this->_error("ftp_unable_to_connect");
  154. }
  155. return FALSE;
  156. }
  157. if( ! $this->_login()) {
  158. if($this->debug === TRUE) {
  159. $this->_error("ftp_unable_to_login");
  160. }
  161. return FALSE;
  162. }
  163. if($this->passive === TRUE) {
  164. ftp_pasv($this->conn_id, TRUE);
  165. }
  166. return TRUE;
  167. }
  168. /**
  169. * 文件夹是否存在
  170. * @param unknown_type $path
  171. */
  172. public function is_dir_exists($path)
  173. {
  174. return $this->chgdir($path);
  175. }
  176. /**
  177. * 目录改变
  178. *
  179. * @access public
  180. * @param string 目录标识(ftp)
  181. * @param boolean
  182. * @return boolean
  183. */
  184. public function chgdir($path = '', $supress_debug = FALSE) {
  185. if($path == '' OR ! $this->_isconn()) {
  186. return FALSE;
  187. }
  188. $result = @ftp_chdir($this->conn_id, $path);
  189. if($result === FALSE) {
  190. if($this->debug === TRUE AND $supress_debug == FALSE) {
  191. $this->_error("ftp_unable_to_chgdir:dir[".$path."]");
  192. }
  193. return FALSE;
  194. }
  195. return TRUE;
  196. }
  197. /**
  198. * 目录生成
  199. *
  200. * @access public
  201. * @param string 目录标识(ftp)
  202. * @param int 文件权限列表
  203. * @return boolean
  204. */
  205. public function mkdir($path = '', $permissions = NULL) {
  206. if($path == '' OR ! $this->_isconn()) {
  207. return FALSE;
  208. }
  209. $result = @ftp_mkdir($this->conn_id, $path);
  210. if($result === FALSE) {
  211. if($this->debug === TRUE) {
  212. $this->_error("ftp_unable_to_mkdir:dir[".$path."]");
  213. }
  214. return FALSE;
  215. }
  216. if( ! is_null($permissions)) {
  217. $this->chmod($path,(int)$permissions);
  218. }
  219. return TRUE;
  220. }
  221. /**
  222. * 上传
  223. *
  224. * @access public
  225. * @param string 本地目录标识
  226. * @param string 远程目录标识(ftp)
  227. * @param string 上传模式 auto || ascii
  228. * @param int 上传后的文件权限列表
  229. * @return boolean
  230. */
  231. public function upload($localpath, $remotepath, $mode = 'auto', $permissions = NULL) {
  232. if( ! $this->_isconn()) {
  233. return FALSE;
  234. }
  235. if( ! file_exists($localpath)) {
  236. if($this->debug === TRUE) {
  237. $this->_error("ftp_no_source_file:".$localpath);
  238. }
  239. return FALSE;
  240. }
  241. if($mode == 'auto') {
  242. $ext = $this->_getext($localpath);
  243. $mode = $this->_settype($ext);
  244. }
  245. $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
  246. $result = @ftp_put($this->conn_id, $remotepath, $localpath, $mode);
  247. if($result === FALSE) {
  248. if($this->debug === TRUE) {
  249. $this->_error("ftp_unable_to_upload:localpath[".$localpath."]/remotepath[".$remotepath."]");
  250. }
  251. return FALSE;
  252. }
  253. if( ! is_null($permissions)) {
  254. $this->chmod($remotepath,(int)$permissions);
  255. }
  256. return TRUE;
  257. }
  258. /**
  259. * 下载
  260. *
  261. * @access public
  262. * @param string 远程目录标识(ftp)
  263. * @param string 本地目录标识
  264. * @param string 下载模式 auto || ascii
  265. * @return boolean
  266. */
  267. public function download($remotepath, $localpath, $mode = 'auto') {
  268. if( ! $this->_isconn()) {
  269. return FALSE;
  270. }
  271. if($mode == 'auto') {
  272. $ext = $this->_getext($remotepath);
  273. $mode = $this->_settype($ext);
  274. }
  275. $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
  276. $result = @ftp_get($this->conn_id, $localpath, $remotepath, $mode);
  277. if($result === FALSE) {
  278. if($this->debug === TRUE) {
  279. $this->_error("ftp_unable_to_download:localpath[".$localpath."]-remotepath[".$remotepath."]");
  280. }
  281. return FALSE;
  282. }
  283. return TRUE;
  284. }
  285. /**
  286. * 重命名/移动
  287. *
  288. * @access public
  289. * @param string 远程目录标识(ftp)
  290. * @param string 新目录标识
  291. * @param boolean 判断是重命名(FALSE)还是移动(TRUE)
  292. * @return boolean
  293. */
  294. public function rename($oldname, $newname, $move = FALSE) {
  295. if( ! $this->_isconn()) {
  296. return FALSE;
  297. }
  298. $result = @ftp_rename($this->conn_id, $oldname, $newname);
  299. if($result === FALSE) {
  300. if($this->debug === TRUE) {
  301. $msg = ($move == FALSE) ? "ftp_unable_to_rename" : "ftp_unable_to_move";
  302. $this->_error($msg);
  303. }
  304. return FALSE;
  305. }
  306. return TRUE;
  307. }
  308. /**
  309. * 删除文件
  310. *
  311. * @access public
  312. * @param string 文件标识(ftp)
  313. * @return boolean
  314. */
  315. public function delete_file($file) {
  316. if( ! $this->_isconn()) {
  317. return FALSE;
  318. }
  319. $result = @ftp_delete($this->conn_id, $file);
  320. if($result === FALSE) {
  321. if($this->debug === TRUE) {
  322. $this->_error("ftp_unable_to_delete_file:file[".$file."]");
  323. }
  324. return FALSE;
  325. }
  326. return TRUE;
  327. }
  328. /**
  329. * 删除文件夹
  330. *
  331. * @access public
  332. * @param string 目录标识(ftp)
  333. * @return boolean
  334. */
  335. public function delete_dir($path) {
  336. if( ! $this->_isconn()) {
  337. return FALSE;
  338. }
  339. //对目录宏的'/'字符添加反斜杠'\'
  340. $path = preg_replace("/(.+?)\/*$/", "\\1/", $path);
  341. //获取目录文件列表
  342. $filelist = $this->filelist($path);
  343. if($filelist !== FALSE AND count($filelist) > 0) {
  344. foreach($filelist as $item) {
  345. //如果我们无法删除,那么就可能是一个文件夹
  346. //所以我们递归调用delete_dir()
  347. if( ! @delete_file($item)) {
  348. $this->delete_dir($item);
  349. }
  350. }
  351. }
  352. //删除文件夹(空文件夹)
  353. $result = @ftp_rmdir($this->conn_id, $path);
  354. if($result === FALSE) {
  355. if($this->debug === TRUE) {
  356. $this->_error("ftp_unable_to_delete_dir:dir[".$path."]");
  357. }
  358. return FALSE;
  359. }
  360. return TRUE;
  361. }
  362. /**
  363. * 修改文件权限
  364. *
  365. * @access public
  366. * @param string 目录标识(ftp)
  367. * @return boolean
  368. */
  369. public function chmod($path, $perm) {
  370. if( ! $this->_isconn()) {
  371. return FALSE;
  372. }
  373. //只有在PHP5中才定义了修改权限的函数(ftp)
  374. if( ! function_exists('ftp_chmod')) {
  375. if($this->debug === TRUE) {
  376. $this->_error("ftp_unable_to_chmod(function)");
  377. }
  378. return FALSE;
  379. }
  380. $result = @ftp_chmod($this->conn_id, $perm, $path);
  381. if($result === FALSE) {
  382. if($this->debug === TRUE) {
  383. $this->_error("ftp_unable_to_chmod:path[".$path."]-chmod[".$perm."]");
  384. }
  385. return FALSE;
  386. }
  387. return TRUE;
  388. }
  389. /**
  390. * 获取目录文件列表
  391. *
  392. * @access public
  393. * @param string 目录标识(ftp)
  394. * @return array
  395. */
  396. public function filelist($path = '.') {
  397. if( ! $this->_isconn()) {
  398. return FALSE;
  399. }
  400. return ftp_nlist($this->conn_id, $path);
  401. }
  402. /**
  403. * 关闭FTP
  404. *
  405. * @access public
  406. * @return boolean
  407. */
  408. public function close() {
  409. if( ! $this->_isconn()) {
  410. return FALSE;
  411. }
  412. return @ftp_close($this->conn_id);
  413. }
  414. /**
  415. * FTP成员变量初始化
  416. *
  417. * @access private
  418. * @param array 配置数组
  419. * @return void
  420. */
  421. private function _init($config = array()) {
  422. foreach($config as $key => $val) {
  423. if(isset($this->$key)) {
  424. $this->$key = $val;
  425. }
  426. }
  427. //特殊字符过滤
  428. $this->hostname = preg_replace('|.+?://|','',$this->hostname);
  429. }
  430. /**
  431. * FTP登陆
  432. *
  433. * @access private
  434. * @return boolean
  435. */
  436. private function _login() {
  437. return @ftp_login($this->conn_id, $this->username, $this->password);
  438. }
  439. /**
  440. * 判断con_id
  441. *
  442. * @access private
  443. * @return boolean
  444. */
  445. private function _isconn() {
  446. if( ! is_resource($this->conn_id)) {
  447. if($this->debug === TRUE) {
  448. $this->_error("ftp_no_connection");
  449. }
  450. return FALSE;
  451. }
  452. return TRUE;
  453. }
  454. /**
  455. * 从文件名中获取后缀扩展
  456. *
  457. * @access private
  458. * @param string 目录标识
  459. * @return string
  460. */
  461. private function _getext($filename) {
  462. if(FALSE === strpos($filename, '.')) {
  463. return 'txt';
  464. }
  465. $extarr = explode('.', $filename);
  466. return end($extarr);
  467. }
  468. /**
  469. * 从后缀扩展定义FTP传输模式 ascii 或 binary
  470. *
  471. * @access private
  472. * @param string 后缀扩展
  473. * @return string
  474. */
  475. private function _settype($ext) {
  476. $text_type = array (
  477. 'txt',
  478. 'text',
  479. 'php',
  480. 'phps',
  481. 'php4',
  482. 'js',
  483. 'css',
  484. 'htm',
  485. 'html',
  486. 'phtml',
  487. 'shtml',
  488. 'log',
  489. 'xml'
  490. );
  491. return (in_array($ext, $text_type)) ? 'ascii' : 'binary';
  492. }
  493. /**
  494. * 错误日志记录
  495. *
  496. * @access prvate
  497. * @return boolean
  498. */
  499. private function _error($msg) {
  500. return @file_put_contents('/tmp/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);
  501. }
  502. }
  503. /*End of file ftp.php*/
  504. /*Location /Apache Group/htdocs/ftp.php*/

以上所述就是本文的全部内容了,希望大家能够喜欢。