項目需要通過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);
}
}
