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

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

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

2019年9月11日に作成されたページです。
情報が古かったり、僕が今以上のど素人だった頃の記事だったりする可能性があります。

どもです。
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)