コメント |
@DIV
http://winofsql.jp/download/ftp_get.lzh
2009/04/13 : 少し変更しました。
夜間バッチだからと、タイムアウトを 1時間も取っていましたが、
意味無いので 30 秒をデフォルトとしました。php での省略値は 90 秒です。
リモートでファイル名にスペースが入ってるファイルはエラーになります。
FFFTP 等で見た時に化けているファイルもダウンロードはできるようですが、
basp21 のメール送信でエラーになりました
@END
サーバーにあるデータの日々のバックアップが目的なので、
タイムスタンプが不一致のファイルのみダウンロードします
夜間バッチを想定しているので、処理結果をメールで送っています。
メール処理には、Windows の COM として有名なフリーソフトの http://www.hi-ho.ne.jp/babaq/basp21.html(Basp21) を使用しています
また、この手の宛先としては、同一タイトルが同日でまとめられる http://mail.google.com/mail/(GMail) が最適です。
除外ディレクトリは、バックアップの必要の無いソフトウェアや画像データのディレクトリに使用すると良いでしょう
php は、cgi 版では無く、http://www.php.net/manual/ja/features.commandline.php(cli 版)を使用します。
php5 では、php-cgi.exe が cgi 版です。
[[UNIX OS の場合]]
( ※ Windows OS では、ファイル一覧取得時の文字列に違いがあります )
@DIV
<?php
// *********************************************************
// FTP サーバからの一括ダウンロード
// *********************************************************
$obj = new http://www.php.net/manual/ja/ref.com.php|(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 = http://www.php.net/manual/ja/function.ftp-rawlist.php|(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,"");
?>
@END
↓ftp_rawlist によるディレクトリ情報
@DIV
-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
@END
|