どもです。
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の場合、わざわざ片付けする必要があるかすら微妙といえば微妙だけど。