ソース掲示板




すべてから検索

キーワード   条件 表示 現行ログ 過去ログ トピックス 名前 本文
PHP による FTPサーバーのデータ一括ダウンロード ( No.0 )
日時: 2013/05/02 00:30
名前: lightbox



http://winofsql.jp/download/ftp_get.lzh

2009/04/13 : 少し変更しました。

夜間バッチだからと、タイムアウトを 1時間も取っていましたが、
意味無いので 30 秒をデフォルトとしました。php での省略値は 90 秒です。

リモートでファイル名にスペースが入ってるファイルはエラーになります。
FFFTP 等で見た時に化けているファイルもダウンロードはできるようですが、
basp21 のメール送信でエラーになりました
サーバーにあるデータの日々のバックアップが目的なので、 タイムスタンプが不一致のファイルのみダウンロードします 夜間バッチを想定しているので、処理結果をメールで送っています。 メール処理には、Windows の COM として有名なフリーソフトの Basp21 を使用しています また、この手の宛先としては、同一タイトルが同日でまとめられる GMail が最適です。 除外ディレクトリは、バックアップの必要の無いソフトウェアや画像データのディレクトリに使用すると良いでしょう php は、cgi 版では無く、cli 版を使用します。 php5 では、php-cgi.exe が cgi 版です。 UNIX OS の場合 ( ※ Windows OS では、ファイル一覧取得時の文字列に違いがあります )
<?php
// *********************************************************
// FTP サーバからの一括ダウンロード
// *********************************************************
$obj		= new COM("Basp21");
$timeout	= 30;
$svname		= "smtpサーバー:587";
$mailto		= "宛先メールアドレス";
$mailfrom	= "送り主メールアドレス\tユーザID:パスワード";
$subj		= "【バックアップ処理】";
$body		= "FTP サーバからの一括ダウンロード\n\n";

# ************************************************
# 接続情報
# ************************************************
$ftp_server	= "ftpサーバー"; 
$ftp_user 	= "ユーザー"; 
$ftp_pass	= "パスワード";

# ************************************************
# 位置情報
# ************************************************
# 最後に / は必要ありません
$base_dir = "/public_html";
$local_dir	= "C:\\user\\land\\public_html";

# ************************************************
# 除外ディレクトリ
# ************************************************
$out = array( 
	"phpmyadmin"
	,"dojo"
	,"pfn"
	,"servletapi-ja-4.0"
);


$base_dir_save = $base_dir;

# ************************************************
# 処理開始
# ************************************************
print "リモートのパス : $base_dir\n";
print "ローカルのパス : $local_dir\n";

print date("Y/m/d H:i:s") . " >>> 処理を開始しました\n";

# ************************************************
# 接続
# ************************************************
$conn = ftp_connect($ftp_server,21,$timeout);
if (!$conn) {
	die('接続できません');
}

# ************************************************
# ログイン
# ************************************************
$result = @ftp_login($conn, $ftp_user, $ftp_pass); 
if (!$result) {
	die('ログインできません');
}

# ************************************************
# パッシブモードをオン
# ************************************************
ftp_pasv($conn, TRUE);

# ************************************************
# 一覧用配列初期化
# ************************************************
$dir = array();
$file = array();
$file_datetime = array();

# ************************************************
# ルートのディレクトリ一覧とファイル一覧の
# 配列を作成する
# ************************************************
$dir[] = $base_dir;	# 開始ディレクトリのセット
$init = true;
for( $pos = 0; $pos < count($dir); $pos++ ) {

	$base_dir = $dir[$pos];
	$list = ftp_rawlist( $conn, $base_dir );
	if ( $init ) {
		$init = false;
# ********************************************
# FTP が不安定で、大量のダウンロードを回避
# したい場合の手動分割処理
# ********************************************
#		$list = array_slice($list, 0, 20);
#		$list = array_slice($list, 20, 20);
#		$list = array_slice($list, 40, 20);
	}

	if ( !$list ) {
		print "----EMPTY : $base_dir\n";
	}
	else {
		print "-------OK : $base_dir\n";
	}

	$max = count($list);
	for( $i = 0; $i < $max; $i++ ) {

		# ********************************************
		# ディレクトリの場合
		# ********************************************
		if ( substr( $list[$i], 0, 1 ) == 'd' ) {

			# ********************************************
			# 配列作成
			# ********************************************
			$data = explode( " ", $list[$i] );

			# ********************************************
			# 一番最後が名前
			# ********************************************
			$target = array_pop( $data );

			# ********************************************
			# 除外処理
			# ********************************************
			$skip = false;
			for( $idx = 0; $idx < count($out); $idx++ ) {
				if ( $out[$idx] == $target ) {
					$skip = true;
					break;
				}
			}
			if ( $skip ) {
				continue;
			}

			# ********************************************
			# 配列にフルパスをセット
			# ********************************************
			if ( $target != '.' && $target != '..' ) {
				$dir[] = $base_dir . '/' . $target;
			}
		}
		# ********************************************
		# ファイルの場合
		# ********************************************
		else {

			# ********************************************
			# 対象外の文字列の処理
			# ********************************************
			if ( substr( $list[$i], 0, 5 ) != 'total' ) {

				# ********************************************
				# 配列作成
				# ********************************************
				$data = explode( " ", $list[$i] );

				# ********************************************
				# 一番最後が名前
				# ********************************************
				$target = array_pop( $data );

				# ********************************************
				# 配列にフルパスをセット
				# ********************************************
				$file[] = $base_dir . '/' . $target;
				$file_datetime[] = $list[$i];
			}
		}
	}
}

# ************************************************
# ディレクトリ一覧からディレクトリを作成
# ************************************************
for( $pos = 0; $pos < count($dir); $pos++ ) {
	$work = str_replace( $base_dir_save, $local_dir, $dir[$pos] );
	$work = str_replace( "/", "\\", $work );
	@mkdir( $work );
}

# ************************************************
# ダウンロード
# ************************************************
$msg = "ダウンロード対象ファイル数 : " . count($file) . "\n";
print $msg;

# 実際にダウンロードしたファイル数
$cnt = 0;

# メールログ用
$body .= $msg;

# ダウンロードループ
for( $pos = 0; $pos < count($file); $pos++ ) {

	# ********************************************
	# ローカルファイルのパスを作成
	# ********************************************
	$work = str_replace( $base_dir_save, $local_dir, $file[$pos] );
	$work = str_replace( "/", "\\", $work );

	# ********************************************
	# リモートのタイムスタンプを作成
	# ********************************************
	$time_remote = ftp_mdtm($conn, $file[$pos]);

	$skip = FALSE;
	# ********************************************
	# ローカルにファイルが存在した場合はタイムスタンプを作成
	# ********************************************
	if ( file_exists( $work ) ) {
		# ********************************************
		# ローカルのタイムスタンプを取得
		# ********************************************
		$time_local = fileatime($work);
		if ( $time_local === FALSE ) {
			$time_local = $time_remote;
		}
		else {
			# ********************************************
			# サーバが正しい事を大前提とし、
			# タイムスタンプが一致したらダウンロードしない
			# ********************************************
			if ( $time_local == $time_remote ) {
				$skip = TRUE;
			}
			else {
				$time_local = $time_remote;
			}
		}
	}
	# ********************************************
	# ローカルにファイルが存在ない場合は、
	# リモートのタイムスタンプを使用
	# ********************************************
	else {
		$time_local = $time_remote;
	}


	if ( !$skip ) {


		# ********************************************
		# ダウンロードのメッセージ作成
		# ********************************************
		$msg = $pos+1 . ":" . str_replace($base_dir_save . "/", "", $file[$pos]) . "\n";

		print $msg;
		$body .= $msg;

		# ********************************************
		# ダウンロード
		# ********************************************
		$ret = @ftp_get( $conn, $work, $file[$pos], FTP_BINARY );
		if ( $ret !== FALSE ) {
			$cnt++;
			# ********************************************
			# ダウンロードされたファイルのタイムスタンプを更新
			# ********************************************
			$ret = @touch( $work, $time_local );
			if ( $ret === FALSE ) {
				$msg = "touch エラー:$work\n";
				$body .= $msg;
			}
		}
		else {
			$msg = "ftp_get エラー:$work:{$file[$pos]}\n";
			$body .= $msg;
		}

	}

}

ftp_close($conn);

$msg = "実際のファイルダウンロード数 : $cnt";
$body .= $msg;
print "$msg\n";
print date("Y/m/d H:i:s") . " >>> 処理が終了しました\n";

$obj->SendMail($svname,$mailto,$mailfrom,$subj,$body,"");

?>
↓ftp_rawlist によるディレクトリ情報
-rw-r--r--  1 lightbox  users    171 Jul 30  2006 .htaccess
-rw-r--r--  1 lightbox  users     45 Jul 30  2006 .htpasswd
-rwxr-xr-x  1 lightbox  users  23006 Jun 20 22:25 admin.cgi
-rw-r--r--  1 lightbox  users   1053 Jun 20 22:30 custom.cgi
-rw-r--r--  1 lightbox  users    473 Jul 30  2006 file_exist.php
-rw-r--r--  1 lightbox  users   8446 Jun 20 22:51 fileman.php
-rw-r--r--  1 lightbox  users   4830 Jun 20 22:25 help.cgi
drwxr-xr-x  2 lightbox  users    512 Aug 10  2006 image
drwxr-xr-x  2 lightbox  users    512 Jun 20 22:24 img