phpのFTP関数でローカルファイルをサーバと同じにする処理を走らせる
2023-12-24 記載
概要 : phpのftp関数でローカルファイルをサーバと同じにする
関連記事:phpのFTP関数でローカルファイルをサーバと同じにする処理を走らせる
Keyword : FTP, php,
cloudfreeのサーバからphpの FTP関数 を使って、ほかのサーバへftpログインしてFTP操作できるのか?「と思いためしたところ、バッチリできました。
クライアントからの接続はもちろん大丈夫ですが、サーバ側からの接続はまた違うかもしれないので確認してみました。
FTP関数
https://www.php.net/manual/ja/ref.ftp.php
ftp_mlsd — ディレクトリに存在するファイルの一覧を返す
この命令が強力で、ローカルのファイル操作はphp+FTPがPowershellなんかよりも便利なのでは?と思うほどでした。
https://localhost/ftpjob.php?jobkey=cloudfree_mywordpress_local_update
でサーバーとローカルのファイル同期をとるphpコードは以下です。
mb_language('Japanese');
mb_internal_encoding('UTF-8');
date_default_timezone_set("Asia/Tokyo");
setlocale(LC_ALL, 'ja_JP.UTF-8');
$sJobkey = $_GET['jobkey'] ?? 'nop';
$cParam = array();
$cParam['dryrun'] = 'no';
if ($sJobkey === 'nop') {
} elseif ($sJobkey === 'cloudfree_mywordpress_local_update') {
$cParam['base_path_src'] = '/cfsid.cloudfree.jp/public_html/mywordpress/';
$cParam['base_path_dest'] = 'c:/home/cfsid/cfsid.cloudfree.jp/public_html/mywordpress/';
//ftp-cloudfree
$ftp_cloudfree = getftp('svXX.cloudfree.ne.jp/cfsid_ftpuser@cfsid.cloudfree.jp/password');
ftp_chdir($ftp_cloudfree, $cParam['base_path_src']);
//ftp-local
$ftp_local = getftp('localhost/ftpuser/password');
ftp_chdir($ftp_local, '/cloudfree_home/cfsid/cfsid.cloudfree.jp/public_html/mywordpress/');
echo '<hr>';
$cParam['subfolder'] = 'yes';
$cParam['delete_localonly'] = 'yes';
GetFile_IfUpdate($ftp_cloudfree, $ftp_local, 'wp-content/uploads/2023/', $cParam);
echo '<hr>';
$cParam['subfolder'] = 'yes';
$cParam['delete_localonly'] = 'yes';
GetFile_IfUpdate($ftp_cloudfree, $ftp_local, 'wp-content/themes/', $cParam);
ftp_close($ftp_cloudfree);
ftp_close($ftp_local);
}
// === function ================================================================
//DESTとSRCの両ファイルの更新日時を比較して、同じでなければSRCファイルをGetしてSRCタイムに書き換える
//$cParam['subfolder']='yes'ならサブフォルダも対象とし再帰関数として作動する
//$cParam['dryrun']='yes'「GetしてSRCタイムに書き換える」は行わない
function GetFile_IfUpdate($ftp_src, $ftp_dest, $sFolder, $cParam) {
echo 'search folder:'.$sFolder."<br>\n";
$aList = ftp_mlsd($ftp_src, $sFolder);
$aList_dest_mdtm = GetDic_mdtm(ftp_mlsd($ftp_dest, $sFolder));
foreach($aList as $item) {
if ($item['type'] == 'dir' && $cParam['subfolder'] == 'yes') {
GetFile_IfUpdate($ftp_src, $ftp_dest, $sFolder.$item['name'].'/', $cParam);
} else if ($item['type'] == 'file') {
$fExist = key_exists($item['name'], $aList_dest_mdtm);
$fDownload = false;
if (!$fExist) {
//ローカルにはないファイル
echo '[NEW]'.$sFolder.$item['name']."<br>\n";
$fDownload = true;
} elseif ($aList_dest_mdtm[$item['name']] != $item['modify']) {
//更新日時が相違のファイル
echo '[Diff]'.$sFolder.$item['name']."<br>\n";
echo date_mdtm($item['modify']).'[svr] != [local]'.date_mdtm($aList_dest_mdtm[$item['name']])."<br>\n";
$fDownload = true;
} else {
//更新日時が同一
}
//ダウンロード
if ($fDownload) {
$local_filename = $cParam['base_path_dest'].$sFolder.$item['name'];
$ftpDateTime = DateTime::createFromFormat('YmdHis', $item['modify'], new DateTimeZone('UTC'));
$ftpDateTime->setTimezone(new DateTimeZone('Asia/Tokyo'));
if ($cParam['dryrun'] != 'yes') {
ftp_get($ftp_src, $local_filename, $cParam['base_path_src'].$sFolder.$item['name'], FTP_BINARY);
touch($local_filename, $ftpDateTime->getTimestamp());
}
echo 'download '.$local_filename."<br>\n";
echo 'modify set:'.$ftpDateTime->format('Y-m-d H:i:s')."<br>\n";
}
if ($fExist) {
unset($aList_dest_mdtm[$item['name']]);
}
}
}
//ローカルのみに存在するファイルに対する操作
if (($cParam['delete_localonly'] === 'yes') && (count($aList_dest_mdtm) > 0)) {
echo "===[delete_localonly]===<br>\n";
//MDTM問い合わせ時に削除しているので、残る要素はローカルにしかないファイル
foreach(array_keys($aList_dest_mdtm) as $key) {
echo $key."<br>\n";
if ($cParam['dryrun'] != 'yes') {
ftp_delete($ftp_dest, $sFolder.$key);
}
}
}
}
//FTPサーバへの接続
function getftp($sServerVal) {
$asServerVal = explode('/', $sServerVal);
$ftp = ftp_connect($asServerVal[0]) or die("Couldn't connect to $asServerVal[0]");
ftp_login($ftp, $asServerVal[1], $asServerVal[2]) or die("Couldn't login");
return $ftp;
}
// 最終更新日時を'Y-m-d H:i:s'文字列として取得
// "20230401235900"->"2023-04-01 23:59:00"
function date_mdtm($sYmdHis) {
$sYmdHis = explode('.', $sYmdHis)[0];
return DateTime::createFromFormat('YmdHis', $sYmdHis, new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
}
//ローカルファイルの最終更新日時をファイル名をkeyに取得する連想配列を返す
// echo Dic_mdtm['index.html']; // '20230401235900'
function GetDic_mdtm($aList_dest) {
$ret = array();
foreach($aList_dest as $item) {
if ($item['type'] === 'file') {
$ret[$item['name']] = $item['modify'];
}
}
return $ret;
}