アップロードしたファイルを確認ページでプレビューした後、本登録というフローがよくありますが、その方法にいくつかテクニックがあると思います。
今回は自作で実装してみたので、メモします。
要件とフロー
ざっくりと要件とフローをまとめます。
- アップロードできるファイルはgif、png、jpg、jpeg、bmp
- アップロードできるファイルサイズは10MBまで
- アップロードされたファイル名を重複ブロックのためリネームする
- アップロード後、ファイルを一時保存して確認ページでプレビューする
- 問題があった場合は再度アップロードする
- 問題なければ、登録と同時に一時保存ファイルを削除して本保存ディレクトリに保存する
ポイントはプレビュー用のファイルは一時保存にする必要があり、登録と同時に一時保存のファイルは削除しなければなりません。
今回のプログラムはそのあたりを記載したいと思います。
HTML
HTMLは以下です。
<form name="sample" method="post" action="sample" enctype="multipart/form-data"> <p><input type="file" name="file"></p> <p>※アップロードできるファイルはgif、png、jpg、jpeg、bmpです。<br> ※アップロードできるファイルサイズは10MBまでです。</p> <br><br> <input type="submit" value="アップロード"> </form>
一時保存ファイルのPHPプログラム
まず、プレビュー用に一時保存ファイルを保存するためのプログラムを記述します。
conf.php
$tempfile = $_FILES['file']['tmp_name']; //一時保存のディレクトリ $date_mkdir_file="tmp_upload"; mkdir($date_mkdir_file, 0777); $uploaddir = $date_mkdir_file."/"; //ファイルリネーム list($file_name,$file_type) = explode(".",$_FILES['file']['name']); $dateformat_uniq=uniqid(date('Ymd')); $dateformat=date("Ymdh")."_".$dateformat_uniq."images"; $uploadfile = "$uploaddir$dateformat.$file_type"; //ファイル名を取得 $fileNM = mb_ereg_replace($uploaddir, "", $uploadfile); //拡張子チェック if(preg_match('/\.gif$|\.png$|\.jpg$|\.jpeg$|\.bmp$/i', $uploadfile)){ $filetype=1;//許可した拡張氏子 }else{ $filetype=2;//許可してない拡張子 } //ファイルサイズチェック $size = 1024*1024*10; //10MB上限設定 $filesize = $_FILES["file"]["size"];//ファイルサイズ取得 $filesize_NUM=$filesize / 1000000;//ファイルサイズをMB単位に計算 $filesize_round=round($filesize_NUM, 2)."MB";//MBを四捨五入 if($filesize < $size){ $filesize_check=1;//サイズ範囲内 } else{ $filesize_check=2;//サイズオーバー } if($filesize_check==2 || $filetype==2){ $err_file_flag=1; } $temp_img_dir=$uploaddir."".$fileNM; if($err_file_flag==1){ $fileinput=<<<END <input type="hidden" name="file" value=""> END; $fileimg=""; } else{ $fileinput=<<<END <input type="hidden" name="file" value="$fileNM"> END; $fileimg=<<<END <p><img src="$uploadfile"></p> END; } print <<<EOF <form name="sample" method="post" action="sample" enctype="multipart/form-data"> EOF; print <<<EOF $fileinput EOF; if (is_uploaded_file($tempfile)) { if($filesize_check==2){ echo "<p>容量がオーバーしています。アップロードできるファイルは10MBまでです。<br>"; echo "ファイルサイズ" . $filesize_round . "<br></p>"; echo "<input type='file' name='file'>"; } elseif($filetype==2){ echo "<p>拡張子不明です。アップロードできるファイルはgif、png、jpg、jpeg、bmpです。</p>"; echo "<input type='file' name='file'>"; } elseif ( move_uploaded_file($tempfile,$uploadfile)) { echo "<p>以下のファイルをご確認ください。</p>" ; echo $fileimg ; } else{ echo "<p>ファイルをアップロードできません。</p>"; echo "<input type='file' name='file'>"; } } else { echo "<p>ファイルが選択されていません。</p>"; echo "<input type='file' name='file'>"; } print <<<EOF </form> EOF;
前提として、一時保存用のディレクトリはtmp_uploadとします。
※本保存用のディレクトリはuploadとします。
※いずれもプログラムファイルと同じ階層に設置します。
//一時保存のディレクトリ $date_mkdir_file="tmp_upload"; mkdir($date_mkdir_file, 0777); $uploaddir = $date_mkdir_file."/";
ファイルのリネームは以下で行っています。
レギュレーションは
Ymdh_uniqid_images.拡張子になります。
$dateformat_uniq=uniqid(date('Ymd')); $dateformat=date("Ymdh")."_".$dateformat_uniq."images";
uniqid関数を使用したのは、重複を避けるためです。最後にimagesと追加しているのは、一時ファイルの削除の際のフラグにしています。
この時点でファイル名を取得します。
$fileNM = mb_ereg_replace($uploaddir, "", $uploadfile);
エラー条件を設定し、$err_file_flagに代入し、出力条件を設定します。
if($filesize_check==2 || $filetype==2){ $err_file_flag=1; } $temp_img_dir=$uploaddir."".$fileNM; if($err_file_flag==1){ $fileinput=<<<END <input type="hidden" name="file" value=""> END; $fileimg=""; } else{ $fileinput=<<<END <input type="hidden" name="file" value="$fileNM"> END; $fileimg=<<<END <p><img src="$uploadfile"></p> END; }
エラーが出た場合は、valueをブランクにしますが、そうでない場合はvalueに$fileNMを入れます。同時にプレビュー様のimgのパスも出力します。
$err_file_flagを使って、その他必要な出力条件を設定します。本来はsubmitボタン等もありますが、今回は省略します。
エラーがなければ、一時保存ファイルをtmp_uploadに保存しプレビューします。
elseif ( move_uploaded_file($tempfile,$uploadfile)) { echo "<p>以下のファイルをご確認ください。</p>" ; echo $fileimg ; }
一時保存ファイルの削除と本保存にファイルを移動
プレビューで問題がなければ、登録となり一時保存ファイルを削除し本保存ディレクトリにファイルを移動します。
thanks.php
$fileName_IMG = $file; $sourceDir = "tmp_upload/".$fileName_IMG; $destinationDir = "upload/".$fileName_IMG; if(rename($sourceDir, $destinationDir)){ $chenge_data=<<<END 成功!! END; } else{ $chenge_data=<<<END 失敗!! END; } $deleteFile = 'images'; $filePath = glob("tmp_upload/*"); foreach($filePath as $value){ if(strpos($value, $deleteFile) !== false){ unlink($value); } }
ファイルの削除と移動にはrename関数を使用します。
tmp_uploadにあるファイルを削除しuploadへと移動しています。
$fileName_IMG = $file; $sourceDir = "tmp_upload/".$fileName_IMG; $destinationDir = "upload/".$fileName_IMG; if(rename($sourceDir, $destinationDir)){ $chenge_data=<<<END 成功!! END; } else{ $chenge_data=<<<END 失敗!! END; }
また、プレビュー後フォームに戻り、再アップロードすることもあります。
その際、プレビューした時点でtmp_uploadには保存されており、再アップロードされたファイルは別のユニークコードを生成されるので、前のファイルと新たなファイルが複数混在していることになります。
本保存は最後にvalueに入っているファイル名となるので、この場合前のプレビューファイルが残っていることになり、よろしくないので、unlink関数を使用してimagesがファイル名に入っているファイルを全て削除しています。
$deleteFile = 'images'; // 削除対象のファイル名またはその一部の文字列 $filePath = glob("tmp_upload/*"); // 削除対象のファイルが保存されているフォルダから全てのファイルパスを取得 foreach($filePath as $value){ if(strpos($value, $deleteFile) !== false){ // パスに削除対象の文字列が含まれていたら、ファイル削除を実行する unlink($value); } }
とりあえず、ここまででやりたいことはできました。
ふーー….
本来sessionを使用するなど、もっと効率的な方法はあるのでしょうが、飽くまで自作ということなのでご勘弁を。
もっと勉強して、アップデートしていきます!