ファイルアップロードの仕方

CGIテクニック集トップへ





概要

HTMLのフォームからファイルをサーバーにアップロードする方法です。メッセージボード5ディスカッションアップダウン2クリプトアップ等、ファイルアップロード機能が付いたCGIで使われています。

必用な処理

  1. PerlのPackage、CGI、File::Copy、File::Basenameを読み込む。
  2. フォームからのデータをCGI.pmで受け取り、オブジェクトを作成する。
  3. サーバーに書き込むファイル名を設定する。
  4. アップロードするファイルオープンし、ファイルハンドルを作成する。
  5. ファイルハンドルをファイルにコピーする。
  6. CGIのオブジェクトをundefする。
  7. 必用であればアップロード後の表示HTMLへ移動する。

サンプルコード

 use CGI;
 use File::Copy;
 use File::Basename;
 
 my $q = new CGI;
 
 my $fname = basename($q->param('upfile'));
 my $path = ".";
 my $newfile = "$path/$fname";
 
 my $fh = $q->upload('upfile');
 copy ($fh, "$newfile");
 undef $q;
 
 print "Location: upload.html\n\n";

コードの解説

前提として以下のHTMLフォームからファイルをアップロードすると仮定します。このフォームはupload.htmlという名前で作成されているとします。

 <form action="./upload.cgi" method="post" enctype="multipart/form-data">
 <input type=file name="upfile">
 <input type=submit name=sub value="Uplaod">
 </form>

methodをpostに指定し、enctypeをmultipart/form-dataに設定します。ファイルをアップロードするフォームのnameをupfileと定義します。アップロードボタン上には「Upload」と表示されます。

 use CGI;
 use File::Copy;
 use File::Basename;

必用なPerlのPackageを読み込みます。CGIはフォームから渡されたデータを利用するために使います。ファイルアップロードも簡単に操作することができます。File::Copyはアップロードしたファイルのデータをサーバー上に書き出すのに利用します。ここではcopyメソッドを利用します。File::Basenameはアップロードした元ファイルのファイル名を抽出し、それをサーバー上に書き出すファイル名として利用するために使います。ここではbasenameメソッドを利用します。

 my $q = new CGI;

CGIのオブジェクトを作成します。この時点でフォームからのデータはメモリ上に取り込まれます。このオブジェクトに対してメソッドを実行することで各種操作が可能になります。

 my $fname = basename($q->param('upfile'));
 my $path = ".";
 my $newfile = "$path/$fname";

サーバー上のファイル名を作成します。$q->param('upfile')により<input type=file name="upfile">タグで渡された値を読み込みます。つまりフォームに入力したファイル名になります。その値に対してbasenameメソッドによりパス部を除去します。 その後サーバー上のアップロードするパスを定義し、ここでは「.」なのでCGIが置いてあるカレントディレクトリとしています。それらを繋げ$newfileにサーバー上のファイル名を作成します。

 my $fh = $q->upload('upfile');

uploadメソッドによりアップロードするファイルのファイルハンドルを作成します。uploadメソッドの返り値はファイルハンドルになります。このファイルハンドルに対して処理をすることでアップロードするファイルを操作することができます。

 copy ($fh, "$newfile");

copyメソッドでファイルハンドルをファイルにコピーします。ファイルハンドルをファイルに書き出せばアップロードできるのでopen, while, binmode, print, closeでもファイルを書き出すことができます。ここではcopyの一コマンドで済ましています。 この時点でファイルのアップロードは完了します。

 undef $q;

CGIのオブジェクトをundefします。アップロードを途中でやめた場合や、エラー処理をする場合に、アップロードされたテンポラリファイルが削除されない場合があるので、CGIのオブジェクトを廃棄することで、自動的にテンポラリファイルが削除されます。ファイルハンドル$fhはクローズする必要はありません。スクリプトの終了と同時にクローズされます。

 print "Location: upload.html\n\n";

必用に応じてアップロード後の処理をします。この場合は元のフォームのHTMLにジャンプするようにしています。

関連するCGIテクニック

サーバー上のファイルをダウンロードさせる方法
サーバー上の古いテンポラリファイルを自動削除
File::Findを使って複数ディレクトリ内の古いテンポラリファイルを自動削除