PHPでファイル・アップローダを作る

(1/1)
今回は、Web経由で任意のファイルを指定ディレクトリに登録するファイル・アップローダを作ってみることにする。

サンプル・プログラム

サンプル・プログラムの解説:準備

アップロード用パス名は固定で、変数 $path_up に代入しておく。これは、各自の環境に合わせて変更してほしい。

  10: $path_up = "./upload/";     //アップロード用パス

プログラムは、アップロードするファイルを指定する部分と、アップロード処理の実施と結果を表示する部分の2つに分かれる。$_FILES 変数に渡された内容によって、2つのプログラムを切り替えることができるようにしてある。

  46: if (isset($_FILES["upload"]) == FALSE) {

サンプル・プログラムの解説:アップロード・ファイル指定

まず、アップロードするファイルの指定だが、これは HTML の <input type="file"> タグを利用する。ここで注意しなければならないのは、バイナリ・ファイルを扱うこともあるので、<form> タグで enctype="multipart/form-data" としてやらなければならない。
あとは、POST メソッドでファイルがアップロードされる。

  49: <form name="add" enctype="multipart/form-data" method="post" action="$myself">
  50: ファイル:
  51: <input name="upload" type="file" size="50" />
  52: <input value="登録" type="submit" />
  53: </form>

この画面では、登録されているファイル一覧も表示するようにした。

  58: $filenames = array();
  59: $n = get_filenames($path_up, $filenames);
  60: if ($n == 0) {
  61:     echo "<<ファイルは登録されていません>>";
  62: else {
  63:     echo "<table border=\"0\">\n";
  64:     echo "<caption>登録ファイル一覧</caption>\n";
  65:     foreach($filenames as $key=>$val) {
  66:         echo "<tr>\n";
  67:         echo "<td><a href=\"" . $path_up . $val . "\" target=\"_blank\">$val</a></td>\n";
  68:         echo "</tr>\n";
  69:     }
  70:     echo "</table>\n";
  71: }

この画面では、登録されているファイル一覧も表示するようにした。
変数 $path_up にあるファイル名一覧を取得するユーザー関数 get_filenames を用意した。
取得したファイル名は、配列変数 $filenames に代入する。引き数に & を付けると、参照による代入を行うことを意味する。
PHP では、ディレクトリを扱うための  opendir  関数が用意されている。これを  fopen  関数のように使い、個々のファイル名を  readdir  関数で読み出していくことができる。
isdir 関数を使い、取得したファイル名がディレクトリか判断する。ファイル名がディレクトリであれば、配列には格納しない。

  14: /**
  15:  * 指定パスのファイル名一覧を取得する
  16:  * @param   string $path ターゲット・パス
  17:  * @param   array  $filenames ファイル名を格納する配列
  18:  * @return  int 取得したファイル数
  19: */
  20: function get_filenames($path, &$filenames) {
  21:     $n = 0;
  22:     if ($dir = opendir($path)) {
  23:         while ($fname = readdir($dir)) {
  24:             if (is_dir($path . $fname))     continue;
  25:             $filenames[$n] = $fname;
  26:             $n++;
  27:         }
  28:     }
  29:     return $n;
  30: }

サンプル・プログラムの解説:ファイル登録実行

次に、ファイルの登録実行である。
アップロードした元ファイル名が $_FILES["upload"]["name"] に代入されているので(元のパス名は含まれない)、これが空でないかどうかをチェックする。空でなければ、登録先のフルネームを変数 $file_name に代入する。
もし $file_name が存在していたら、登録処理は中止する。
アップロードされたファイルそのものは、一時ファイル $_FILES["upload"]["tmp_name"] に格納されている。これを $file_name へコピーしてやる。

  79: if (! empty($_FILES["upload"]["name"])) {
  80:     $file_name = $path_up . $_FILES["upload"]["name"];
  81:     if (! file_exists($file_name)) {
  82:         $ret = copy($_FILES["upload"]["tmp_name"], $file_name);
  83:         echo "> " . $_FILES["upload"]["name"];
  84:         if ($ret)   echo " の登録に成功<br />\n";
  85:         else        echo " の登録に失敗<br />\n";
  86:     } else {
  87:         echo "> 同名ファイルが存在するため登録中止<br />\n";
  88:     }
  89: }

登録ページへ「戻る」ボタンを用意しておいた。

  92: <form method="post" action="$myself">
  93: <input type="submit" value="戻る" />
  94: </form>

さらに、アップロード時にパスワードを登録させ、パスワードが合致する場合には削除できるようにする機能や、アップロードするファイル拡張子を限定するような機能を追加すれば、画像掲示板に発展させることもできるだろう。
なお、今回のファイル・アップローダは、日本語ファイル名を扱うことを想定して、 mb_internal_encoding  関数で文字コードを指定している。
この部分は OS のファイルシステムに依存することがあるようだ。一般的には Shift JIS 指定でよいだろう。
Windows では、UTF-16UTF-32 でも正常に動作するが、UTF-8 では動作しなかった。

  12: mb_internal_encoding('SJIS');

(この項おわり)
header