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); } }