閲覧者側にあるファイルをページ作者側へ送信する機構を
作ることができます。つまりファイルのuploadです。
この機構を応用すれば、画像ファイルを閲覧者から送ってもらって
展覧会を開くこともできますし、もらった画像を加工して閲覧者に送り返す
加工工場のようなこともできます。
ファイルをuploadするためのHTMLのページにはやはりFORMを使います。
前に解説したFORMとはちょっと形式が異なります。
uploadされたデータを受け取って適切に保存する機構はもちろんCGIです。
本節では upload の窓口となるHTMLのページの作り方と、
そのデータを受け付けて処理するCGIプログラムの作り方を簡単に解説します。
ただし、この受け付けCGIをいい加減に設計すると、
巨大なセキュリュティーホールが開くことになり、
ネットワーク犯罪者(cracker)の格好の標的となりますので、
十分注意して設計してください。
FORMを使いますが、前節のFORMとは形式が異なります。
次の例は投稿者の名前と、投稿ファイルの投稿者側でのパスを
入力するFORMを作ります。
<FORM ENCTYPE="multipart/form-data" ACTION="multform.cgi" METHOD="POST"> Author: <INPUT TYPE="TEXT" NAME="author"><BR> Path: <INPUT TYPE="FILE" NAME="fname"SIZE=48><BR> <INPUT TYPE="SUBMIT" VALUE="Upload"> </FORM>
TYPE=TEXT のINPUTタグは従来通りの一行書き込みフィールドを作ります。
TYPE=FILE のINPUTタグは、uploadするファイルパス名を書き込む
フィールドを作ります。指定された変数 "fname" にはファイルのパス名
を除いたファイル名だけが格納されるようです。
パスは閲覧者のサイトのルートからの絶対パスなのでそれを記入するのは
大変です。なので普通はこのフィールドの横に自動的にbrowseボタンが
付加されます。このボタンを押すと、ファイル選択のためのウィンドウが
開きます。
submitボタンで、これらデータがupload用に加工(encode)されて
uploadされます。
先の例のFORMの "author"変数に "Naoki" と入力して、 "fname"変数に"/home/naoki/piblic_html/index.html" と 入力したとしましょう。browserがこれらのデータをencodeして CGIに送るデータは以下のようになります。
-----------------------------10625178864862561851508029952 Content-Disposition: form-data; name="author" Naoki -----------------------------10625178864862561851508029952 Content-Disposition: form-data; name="fname"; filename="index.html" Content-Type: text/html This is the first line of the file. The data of file is not encoded any more, just located here. This is the last line. -----------------------------10625178864862561851508029952--
一つのINPUT項目は「 Content-Disposition: form-data;」で始まって 「--------------------」の行で終わっています。実はこの 「--------------------」の行の直前には「0x0d 0x0a」の2文字が 必ずあります。MS-DOSでのテキストファイルでは、このコードは改行を 表すのでファイル中に多く含まれますが、UNIXやMacでは バイナリファイルでない限り含まれません。そこで「0x0d 0x0a」と 「--------------------」が連続していたら項目の終りと判断することが できるでしょう。
この範囲の中で TYPE=FILE以外の変数の名前は name=""で表され、空行を
置いて、その値が行頭に置かれます。
TYPE=FILEの変数の名前も name=""で表されますが、それに続いて
; filename="" でファイルの名前が表されます。次の行でファイルの形式が
示され、空行を置いて、ファイル内容がほぼそのまま置かれ、空行で
終ります。
このとおりデータのencodeのされ方は前節での通常のFORMに比べて遥かに 簡単です。このデータからファイルの中身のデータを取り出して セーブするCGIは簡単に作れそうですが、細かい面倒なことが たくさんあります。MicroSoft Windowsでは終端コードが勝手に変換 されてしまうので、それを防ぐために、プログラム冒頭で 広域変数 _fmode の設定と次の関数を実行しておかなければなりません。
_fmode = _O_BINARY; _setmode( 0, _O_BINARY );
uploadされたファイルを受け取ってセーブするには、そのCGIが指定の ディレクトリにファイルを書き込むことができるようpermissionまたは Sbitが設定されていないとなりません。Sbitについては次章を参照ください。
私が色々試してみたところ、upload受付用のCGIの出力メッセージが 4kbyteを越えると、そのCGIの出力関数で出力が詰まって動かなくなる ようです。なので例えば、uploadされた4kbyte以上のテキストファイル の中身を表示しようとすると、CGIが途中で動けなくなり、いつまで待っても browserにCGIの出力結果が送られてこないことになります。 この現象がhttpdの仕様なのかバグなのかはわかりません。
ファイル終端コードの検知を除いて、このデータのdecode作業は容易なので その詳細は詳しく説明はしません。ここに私が作成したupload受付用の CGIのソースを用意しておきましたので参考にしてください。 ただしセキュリュティー防護の対策は全くしていないので気を付けて下さい。
multform.cc