ど素人から毛を生やす。<延>

FTPに同名ファイルが無ければ新規作成、あれば追記

Web > PHP 2019年9月11日(最終更新:2月前)

どもです。
PHPでFTPに接続し、出力ファイルと同名ファイルが無ければ新規作成、あれば追記がやりたかった。


//ログイン
$ftp_stream = ftp_connect($host);
$login = ftp_login($ftp_stream, $user, $pass);
if(!$login){
	return false;
}

//ファイル一覧を取得
$list = ftp_nlist($ftp_stream, $directoryPath);
if($list===false){
	return false;
}

//$preexistフラグがtrueなら、既存ファイルあり
$preexist = false;
if(in_array($filePath, $list, true)){
	$preexist = true;
}

ここまでは問題ないです。

問題はここから。
上書きだけなら、


//テンポラリファイルを作成
$tmpfile = tmpfile();
$tmpFileInfo = stream_get_meta_data($tmpfile);
$tmpFilePath = $tmpFileInfo["uri"];

//テンポラリファイルに書き出し
fwrite($tmpfile, $outputData);

//FTPアップロード(既存ファイルがあったら上書きする)
ftp_put($ftp_stream, $filePath, $tmpFilePath, FTP_BINARY);

//片付け
fclose($tmpfile);
ftp_close($ftp_stream);

これで事足ります。
では、追記をしたい場合は。


//テンポラリファイルを作成
$tmpfile = tmpfile();
$tmpFileInfo = stream_get_meta_data($tmpfile);
$tmpFilePath = $tmpFileInfo["uri"];

if($preexist){
	//FTPファイルに既存の内容を展開
	ftp_fget($ftp_stream, $tmpfile, $filePath, FTP_BINARY);
}

//テンポラリファイルに書き出し
fwrite($tmpfile, $outputData);

//FTPアップロード(既存ファイルがあったら上書きする)
ftp_put($ftp_stream, $filePath, $tmpFilePath, FTP_BINARY);

//片付け
fclose($tmpfile);
ftp_close($ftp_stream);

だーいぶ昔に書き込みモードに関する記事を書きましたが、テンポラリファイルの初期値は「w+」
追記モードにする必要あるかな?と思いましたが、どうやら不要のようです。

さて、実用性を考えると、ここまでやっておきたいかな。


$filePath = $directoryPath.$fileName;
$backupPath = $directoryPath.'_backup.csv';

//テンポラリファイルを作成
$tmpfile = tmpfile();
$tmpFileInfo = stream_get_meta_data($tmpfile);
$tmpFilePath = $tmpFileInfo["uri"];

if($preexist){
	//既存ファイルをリネーム
	if(!ftp_rename($ftp_stream, $filePath, $backupPath)){
		trigger_error('追記対象のファイルが途中で消失');
	}
	
	//リネームしたファイルを取得してテンポラリファイルに展開
	ftp_fget($ftp_stream, $tmpfile, $backupPath, FTP_BINARY);
}

//テンポラリファイルに書き出し
fwrite($tmpfile, $outputData);

//出力とリネーム
ftp_put($ftp_stream, $backupPath, $tmpFilePath, FTP_BINARY);
if(!ftp_rename($ftp_stream, $backupPath, $filePath)){
	trigger_error('ファイルのリネームに失敗');
}

//片付け
fclose($tmpfile);
ftp_close($ftp_stream);

もっと言えば、set_error_handlerした上でtry-catch-finallyにしてfinally中で片付けするべきなんだけど。

しかし正直、finallyの使いどころがよく分からない実情。
try-catchで例外が発生しても処理が止まらない以上、try-catchの外後ろに書いてもfinallyと結果が変わらない、よね?

まぁPHPの場合、わざわざ片付けする必要があるかすら微妙といえば微妙だけど。

この記事は役に立ちましたか?
  • _(:3」∠)_ 面白かった (0)
  • (・∀・) 参考になった (0)
  • (`・ω・´) 役に立った (0)