PHP使用FTP转移文件夹以及子文件夹

项目需要通过php调用ftp转移一个文件夹以及所有的内容到另一台服务器,刚听到这个需求,简直是一头雾水,可是php就是php,ftp被默认支持了。于是谷歌了一下ftp的知识,看了看php的api,有了个不怎么完美的解决方案。

<?php
class FtpUpload {
	/**
	 * 保存所有的目录
	 * @var array
	 */
	private $dirs;
	/**
	 * 保存所有的文件
	 * @var array
	 */
	private $files;
	/**
	 * FTP地址
	 * @var string
	 */
	private $host;
	/**
	 * FTP用户名
	 * @var string
	 */
	private $usr;
	/**
	 * FTP密码
	 * @var unknown_type
	 */
	private $pwd;
	/**
	 * FTP链接
	 * @var resource
	 */
	private $conn_id;
	/**
	 * FTP保存上传文件的目标目录
	 * @var string
	 */
	private $dst;
	
	/**
	 * 构造
	 * @param string $host
	 * @param string $usr
	 * @param string $pwd
	 * @param string $prjname
	 * @param string $dst
	 */
	public function __construct($host, $usr, $pwd, $prjname, $dst) {
		//初始化
		$this->dirs = array ();
		$this->files = array ();
		$this->listDir ( $prjname );
		$this->host = $host;
		$this->usr = $usr;
		$this->pwd = $pwd;
		$this->dst = $dst;
		//ftp连接 
		$this->conn_id = ftp_connect ( $this->host, 21 ) or die ( "Cannot connect to host" );
		//ftp 登陆
		ftp_login ( $this->conn_id, $this->usr, $this->pwd ) or die ( "Cannot login" );
		//开启passive模式
		ftp_pasv ( $this->conn_id, true );
	}
	/**
	 * 析构,释放FTP链接
	 */
	public function __destruct() {
		ftp_close ( $this->conn_id );
	}
	/**
	 * 递归遍历要上传的文件夹,并分类文件夹与文件,分别存入对应的array
	 * @param unknown_type $dirname
	 */
	private function listDir($dirname) {
		$dir = opendir ( $dirname );
		while ( ($file = readdir ( $dir )) != false ) {
			if ($file == "." || $file == "..") {
				continue;
			}
			if (is_dir ( $dirname . "/" . $file )) {
				array_push ( $this->dirs, $dirname . "/" . $file );
				$this->listDir ( $dirname . "/" . $file );
			} else {
				array_push ( $this->files, $dirname . "/" . $file );
			}
		}
	}
	
	/**
	 * 上传文件
	 */
	public function upload() {
		$this->mkdirs ();
		//上传文件
		foreach ( $this->files as $f ) {
			//区分BINARY和ASCII,可以根据自己的需要微调
			if ($this->endsWith ( $f, ".jpg" ) || $this->endsWith ( $f, ".png" ) || $this->endsWith ( $f, ".gif" ) || $this->endsWith ( $f, ".exe" ) || $this->endsWith ( $f, ".zip" ) || $this->endsWith ( $f, ".swf" ) || $this->endsWith ( $f, ".db" ) || $this->endsWith ( $f, ".dll" ))
				$upload = ftp_put ( $this->conn_id, $f, $f, FTP_BINARY );
			else
				$upload = ftp_put ( $this->conn_id, $f, $f, FTP_ASCII );
		}
	}
	
	/**
	 * 创建所需的文件夹
	 */
	private function mkdirs() {
		ftp_mkdir ( $this->conn_id, $this->dst );
		ftp_chdir ( $this->conn_id, $this->dst );
		foreach ( $this->dirs as $d ) {
			ftp_mkdir ( $this->conn_id, $d );
		}
	}
	/**
	 * 判断目标字符串$haystack是否以指定字符串$needle结尾
	 * @param string $haystack
	 * @param string $needle
	 * @return boolean
	 */
	private function endsWith($haystack, $needle) {
		$length = strlen ( $needle );
		if ($length == 0) {
			return true;
		}
		return (substr ( $haystack, - $length ) === $needle);
	}
}

不知道为啥,在自己的ftp服务器运行良好,换做公司的服务器就悲剧的挂掉了,真心不解,难道是不同的ftp服务器支持的不一样?

于是出现了下面的版本。只是把传输文件放在了遍历文件夹的方法里面了,结果还是比较欣慰的。只是如果文件大了,速度很慢不说,还会出点问题。真正到服务器的文件比原先的文件少了那么一点点。迷茫了。有高手可以指点一下吗?

<?php
class FtpUpload {
	private $host;
	private $usr;
	private $pwd;
	private $conn_id;
	private $dst;
	
	public function __construct($host, $usr, $pwd, $prjname, $dst) {
		$this->host = $host;
		$this->usr = $usr;
		$this->pwd = $pwd;
		$this->dst = $dst;
		//ftp连接 
		$this->conn_id = ftp_connect ( $this->host, 21 ) or die ( "Cannot connect to host" );
		//ftp 登陆
		ftp_login ( $this->conn_id, $this->usr, $this->pwd ) or die ( "Cannot login" );
		//开启passive模式
		ftp_pasv ( $this->conn_id, true );
		$this->listDir ( $prjname );
	}
	public function __destruct() {
		ftp_close ( $this->conn_id );
	}
	private function listDir($dirname) {
		set_time_limit(0);
		//ftp_mkdir($this->conn_id, $dirname);
		$dir = opendir ( $dirname );
		while ( ($file = readdir ( $dir )) != false ) {
			if ($file == "." || $file == "..") {
				continue;
			}
			if (is_dir ( $dirname . "/" . $file )) {
				array_push ( $this->dirs, $dirname . "/" . $file );
				echo $dirname . "/" . $file . "<br/>";
				echo "pwd /$dirname <br/>";
				ftp_chdir ( $this->conn_id, "/$dirname" );
				echo "mkdir $file <br/>";
				ftp_mkdir ( $this->conn_id, $file );
				$this->listDir ( $dirname . "/" . $file );
			} else {
				array_push ( $this->files, $dirname . "/" . $file );
				echo "pwd /$dirname <br/>";
				ftp_chdir ( $this->conn_id, "/$dirname" );
				echo "put $file <br/>";
				if ($this->endsWith ( $file, ".jpg" ) || $this->endsWith ( $file, ".png" ) || $this->endsWith ( $file, ".gif" ) || $this->endsWith ( $file, ".exe" ) || $this->endsWith ( $file, ".zip" ) || $this->endsWith ( $file, ".swf" ) || $this->endsWith ( $file, ".db" ) || $this->endsWith ( $file, ".dll" ))
					$upload = ftp_put ( $this->conn_id, $file, $dirname . "/" . $file, FTP_BINARY );
				else
					$upload = ftp_put ( $this->conn_id, $file, $dirname . "/" . $file, FTP_ASCII );
				echo $dirname . "/" . $file . "<br/>";
			}
		}
	}
	
	private function endsWith($haystack, $needle) {
		$length = strlen ( $needle );
		if ($length == 0) {
			return true;
		}
		return (substr ( $haystack, - $length ) === $needle);
	}
}

  

原文地址:https://www.cnblogs.com/codeplus/p/2618058.html