JavaScript プログラミング講座

 
 

静的なアップロードについて(フォーム要素のみ)

 


■フォーム要素のみを使った静的なアップロード

 
<FORM> 要素を使用すると、ファイルをアップロードする事ができます。
 
HTML の機能だけで実現できます。
 
ここでは、JavaScript を使わない、静的なフォーム要素の使い方を確認します。
 

■フォームを配置する

 
■フォーム要素の機能について
 
フォーム要素については、こちらで解説しています。
 
<FORM> 要素の中には、コントロール要素を配置する事ができます。
 
フォームは、コントロール要素の namevalue 属性値を、外部に送信できます
 
■フォームを設定する

以下の属性値を設定します。
 
プロパティ名説明
actionStringアクセス先となる CGI の URL アドレスを設定する。
targetStringページを開くターゲットウィンドウ名を設定する。
acceptCharsetStringリクエストの「文字セット」を設定する。
methodStringリクエストの「HTTP メソッド」を設定する。(GET、POST)
enctypeStringリクエストの「コンテンツタイプ」を設定する。
 
action 属性には、アップロード先の CGI の URL を設定します。
 
method 属性には、"post" を指定します。
 
enctype 属性には、"multipart/form-data" を指定します。
 
フォームを配置し、ファイルアップロード用の属性値を設定する

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >

    </form>

  </body>
</html>
 

■送信用のボタンを配置する


サブミット用のボタンを追加するには、<input type="submit"> 要素を使用します。
 
送信用のボタンについては、こちらで解説しています。
 
フォーム内に、送信用ボタンを配置する

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >

      <input type="submit" value="送信" >

    </form>

  </body>
</html>
 

■ファイル選択コントロールを配置する


ファイル選択コントロールを配置するには、<input type="file"> 要素を使用します。
 
ファイル選択コントロールについては、こちらで解説しています。
 
■名前を設定する

name 属性を使って、好きな名前を設定します。
 
この名前情報は、ファイルデータと共に、サーバーに送信されます。
 
フォーム内に、ファイル選択コントロールを配置する

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >

      <input type="file" name="input_file" > <br>

      <input type="submit" value="送信" >

    </form>

  </body>
</html>
 
■名前が重複する場合

複数のコントロール要素に、同じ名前を付ける事もできます。
 
この場合、サーバー側では、配列として取り扱われます。
 
1つの名前に、複数の値を持つ状態となります。
 
PHP に送信する場合、名前の最後尾に "[]" を、明示的に記述する必要があります。
 

■複数のファイルアップロードに対応する


■複数のファイル選択コントロールを配置する

ファイル選択コントロールを、複数配置します。
 
フォーム内に、複数のファイル選択コントロールを配置する

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >

      <input type="file" name="input_file0" > <br>
      <input type="file" name="input_file1" > <br>
      <input type="file" name="input_file2" > <br>

      <input type="submit" value="送信" >

    </form>

  </body>
</html>
 
■1つのコントロールで、複数のファイル選択に対応する(HTML5 世代)

multiple 属性を追加します。
 
1つのコントロールで、複数のファイルを選択できるようになります。
 
複数のファイルを選択可能なコントロールを配置する(HTML5 世代)

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >

      <input type="file" name="input_file" multiple > <br>

      <input type="submit" value="送信" >

    </form>

  </body>
</html>
 

■フォームの送信について


フォームからサブミットを行うと、送信が開始されます。
 
フォーム内のコントロール要素の namevalue 属性値が、自動的に送信されます。
 
ファイルが選択されている場合、ファイルデータも送信されます。
 
通常の場合、フォームの送信を行うと、画面の遷移が発生します。
 
アクセス先の URL ページが、新しく開かれます。
 
■ブラウザを使って通信内容を確認する
 
ブラウザの開発者向けツールを使用すると、通信内容を確認する事ができます。
 
使用方法は、こちらで解説しています。
 


 

動的なアップロードについて(フォーム要素 + JS)

 


■ JavaScript を使った動的なアップロード

 
JavaScript を使用すると、画面が遷移しない、Ajax 風のアップロードを実現できます。
 
ここでは、Internet Explorer 6 でも動作する方法について解説します。
 

■フォームを配置する

 
■フォームを配置する
 
フォーム要素のみを使ったアップロードについては、こちらで解説しています。
 
action 属性には、静的なアップロード用の URL アドレスを記述しておきます。
 
JavaScript が利用できない場合、ここに送信されます。
 
シンプルなアップロード用のフォーム

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >
      <input type="file" name="input_file" > <br>
      <input type="submit" value="送信" >
    </form>

  </body>
</html>
 

■受信用のインラインフレームを配置する

 
■インラインフレームを配置する
 
受信用の <IFRAME> 要素を配置します。
 
<IFRAME> 要素については、こちらで解説しています。
 
この要素は、ユーザーからは見えないようにします。
 
スタイルに、display:none; などを指定します。
 
■ウィンドウ名を設定する
 
name 属性に、好きなウィンドウ名を設定します。
 
ここでは、"form_response" とします。
 
■設置例
 
受信用の隠しインラインフレームを配置する

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >
      <input type="file" name="input_file" > <br>
      <input type="submit" value="送信" >
    </form>

    <iframe name="form_response" style="display:none;" ></iframe>

  </body>
</html>
 

■フォームの属性値を動的に変更する

 
■フォーム要素を取得する
 
フォーム要素を取得する方法については、こちらで解説しています。
 
■フォームの設定を変更する

JavaScript から、以下のプロパティを変更します。
 
JavaScript が利用可能な場合、変更したアドレス先に送信されます。
 
プロパティ名説明
actionStringアクセス先となる CGI の URL アドレスを設定する。
targetStringページを開くターゲットウィンドウ名を設定する。
 
■変更例
 
フォームの送信先と、ターゲットを変更する

<html>
  <body>

    <form id="my_form" action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >
      <input type="file" name="input_file" > <br>
      <input type="submit" value="送信" >
    </form>

    <iframe name="form_response" style="display:none;" ></iframe>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// フォーム要素を取得する
	// ------------------------------------------------------------
	// "my_form" という ID 属性のエレメントを取得する
	var form = document.getElementById("my_form");

	// ------------------------------------------------------------
	// フォームの設定を変更する
	// ------------------------------------------------------------
	// アクセス先を変更する
	form.action = "http://example.com/cgi-bin/upload.cgi?type=text";

	// ターゲットウィンドウを設定する
	form.target = "form_response";

    //-->
    </script>

  </body>
</html>
 

■セキュリティについて


■生成元(オリジン)について
 
生成元(オリジン)とは、自身のリソースが格納されている場所です。
 
プロトコルドメインポート番号」の3つを合わせたものです。
 
 
■同一生成元ポリシー (Same-Origin Policy) について
 
「現在の URL」と「アクセス先 URL」のオリジンは、一致している必要があります。
 
オリジンが一致しない場合、レスポンス結果を得る事はできません。
 

■インラインフレームからレスポンスを取得する


■インラインフレーム内の読み込みが完了したか監視する
 
onload イベントを使用します。
 
このイベントが発行された場合、フォームの送受信処理が完了しています。
 
Internet Explorer 8 以前では、かわりに onreadystatechange イベントを使用します。
 
■インラインフレーム内のコンテンツを取得する
 
インラインフレーム内にアクセスする方法については、こちらで解説しています。
 
オリジンが一致していない場合、アクセスは拒否されます。
 
■取得例
 
インラインフレーム内のコンテンツを取得する(自身とアクセス先の URL のオリジンが一致する場合のみ動作する)

<html>
  <body>

    <form id="my_form" action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >
      <input type="file" name="input_file" > <br>
      <input type="submit" value="送信" >
    </form>

    <iframe id="my_iframe" name="form_response" style="display:none;" ></iframe>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// インラインフレーム内の読み込み完了を監視するコンストラクタ
	// ------------------------------------------------------------
	function IFrameElementObserverContentLoaded (iframe,callback){

		// ------------------------------------------------------------
		// 初期化
		// ------------------------------------------------------------
		var handler;
		var iframe_window = iframe.contentWindow;
		if(iframe.addEventListener){
			handler = function (e){
				callback();
			};
			iframe.addEventListener("load" , handler);
		}else if(iframe.attachEvent){
			handler = function (e){
				try {
					if(iframe_window.document.readyState === "complete"){
						callback();
					}
				}catch(e){
				}
			};
			iframe.attachEvent("onreadystatechange" , handler);
		}

		// ------------------------------------------------------------
		// 開放する
		// ------------------------------------------------------------
		this.release = function(){
			if(!handler) return;
			if(iframe.removeEventListener){
				iframe.removeEventListener("load" , handler);
			}else if(iframe.detachEvent){
				iframe.detachEvent("onreadystatechange" , handler);
			}
			handler = null;
		};
	}

	// ------------------------------------------------------------
	// エレメントの内容を文字列として取得する関数
	// ------------------------------------------------------------
	function ElementGetTextContent(element){
		if(element.textContent !== undefined){
			return element.textContent;
		}
		if(element.innerText !== undefined){
			return element.innerText;
		}

		return "";
	}


	// ------------------------------------------------------------
	// 各要素を取得する
	// ------------------------------------------------------------
	// "my_form" という ID 属性のエレメントを取得する
	var form = document.getElementById("my_form");

	// "my_iframe" という ID 属性のエレメントを取得する
	var iframe = document.getElementById("my_iframe");

	// ------------------------------------------------------------
	// フォームの設定を変更する
	// ------------------------------------------------------------
	// アクセス先を変更する
	form.action = "http://example.com/cgi-bin/upload.cgi?type=text";

	// ターゲットウィンドウを設定する
	form.target = "form_response";

	// ------------------------------------------------------------
	// サブミット直前に実行されるイベント
	// ------------------------------------------------------------
	form.onsubmit = function (e){

		// ------------------------------------------------------------
		// インラインフレーム内の読み込み完了を監視する
		// ------------------------------------------------------------
		var observer = new IFrameElementObserverContentLoaded (iframe , function(){

			// ------------------------------------------------------------
			// 監視を終了する(ここでは1回だけ監視する)
			// ------------------------------------------------------------
			observer.release();
			observer = null;

			// ------------------------------------------------------------
			// インラインフレーム内のコンテンツを取得する
			// ------------------------------------------------------------
			try{
				// インラインフレーム内の Window オブジェクトを取得する
				var iframe_window = iframe.contentWindow;

				// Document オブジェクトを取得する
				var iframe_document = iframe_window.document;

				// HTMLHtmlElement オブジェクトを取得する
				var html_element = iframe_document.documentElement;

				// 自身を含む HTML 文字列を取得する
				var str_html = html_element.outerHTML;
				
				// エレメントの内容をテキストとして取得する
				var str_text = ElementGetTextContent(html_element);

				// 出力テスト
				console.log(str_html);
				console.log(str_text);

			}catch(e){

				// 出力テスト(セキュリティエラーなど)
				console.log(e);
			}

		});

	};

    //-->
    </script>

  </body>
</html>
 

■フォーム関連の機能について

 
■送信データを動的に追加する
 
送信データを動的に追加する方法については、こちらで解説しています。
 
■送信データを動的に変更する
 
送信データを動的に変更する方法については、こちらで解説しています。
 
■ JavaScript から送信を開始する
 
JavaScript から送信を開始するには、submit() メソッドを使用します。
 
■サブミット直前であるか監視する
 
サブミット直前であるか監視するには、onsubmit イベントを使用します。
 
フォームの送信は、中止する事もできます。
 


 

HTML5 世代のアップロードについて(XHR + FormData)

 


■ HTML5 世代のアップロード

 
XMLHttpRequestFormData を使用します。
 
進捗状況の確認など、リッチなアップロードを実現できます。
 
Internet Explorer 9 以前では、かわりにこちらの方法を使用します。
 

■送信可能なファイルについて

 
■ Blob オブジェクトを作成する
 
一時的な仮想ファイルを用意し、アップロードできます。
 
任意のバッファから、Blob オブジェクトを作成できます。
 
■ File オブジェクトを取得する
 
ユーザーが選択(許可)したローカルファイルを、アップロードできます。
 
UI を経由して、File オブジェクトを取得します。
 

■セキュリティについて


■生成元(オリジン)について
 
生成元(オリジン)とは、自身のリソースが格納されている場所です。
 
プロトコルドメインポート番号」の3つを合わせたものです。
 
 
■同一生成元ポリシー (Same-Origin Policy) について
 
「現在の URL」と「アクセス先 URL」のオリジンは、一致している必要があります。
 
オリジンが一致しない場合、レスポンス結果を得る事はできません。
 

■フォームを利用したアップロードについて

 
■フォームを配置する
 
フォーム要素のみを使ったアップロードについては、こちらで解説しています。
 
action 属性には、静的なアップロード用の URL アドレスを記述しておきます。
 
JavaScript が利用できない場合、ここに送信されます。
 
シンプルなアップロード用のフォーム

<html>
  <body>

    <form action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >
      <input type="file" name="input_file" > <br>
      <input type="submit" value="送信" >
    </form>

  </body>
</html>
 

■ XHR 通信を開始する


■フォームの送信を中止する
 
JavaScript が利用できる場合、フォームの送信は使用しません。
 
フォームの送信を中止するには、onsubmit イベントを使用します。
 
フォームの送信を中止して、かわりに XHR 通信を行います。
 
■ FormData クラスについて
 
FormData クラスについては、こちらで解説しています。
 
<FORM> 要素内に存在する、すべてのコントロール要素の namevalue 属性値を抽出し、1つの FormData オブジェクトにまとめる事ができます。
 
■フォームから、FormData オブジェクトを作成する
 
フォームから、FormData オブジェクトを作成します。
 
作成方法については、こちらで解説しています。
 
■XHR 通信を開始する
 
XHR 通信を行うと、FormData オブジェクトを、外部に送信する事ができます。
 
XMLHttpRequest については、こちらで解説しています。
 
HTTP メソッドには、POST メソッドを指定します。
 
送信先を変更して、Ajax 用のレスポンス結果を取得します。
 
■送信例
 
FormData オブジェクトを XHR で送信する(自身と送信先のオリジンが一致する場合のみ動作する)

<html>
  <body>

    <form id="my_form" action="http://example.com/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" >
      <input type="file" name="input_file" > <br>
      <input type="submit" value="送信" >
    </form>

    <script type="text/javascript">
    <!--
	// 匿名関数を即時実行
	(function(){

		// ------------------------------------------------------------
		// サポートチェック
		// ------------------------------------------------------------
		if(!(window.addEventListener)) return;
		if(!(window.FormData)) return;

		// ------------------------------------------------------------
		// フォーム要素を取得する
		// ------------------------------------------------------------
		// "my_form" という ID 属性のエレメントを取得する
		var form = document.getElementById("my_form");

		// ------------------------------------------------------------
		// サブミット直前に実行されるイベント
		// ------------------------------------------------------------
		form.addEventListener("submit" , function(e){

			// ------------------------------------------------------------
			// デフォルトの動作をキャンセル(フォームの送信を中止)
			// ------------------------------------------------------------
			e.preventDefault();

			// ------------------------------------------------------------
			// FormData オブジェクトを作成する
			// ------------------------------------------------------------
			var form_data = new FormData(form);

			// ------------------------------------------------------------
			// XMLHttpRequest オブジェクトを作成
			// ------------------------------------------------------------
			var xhr = new XMLHttpRequest();

			// ------------------------------------------------------------
			// XHR 通信に成功すると実行されるイベント
			// ------------------------------------------------------------
			xhr.onload = function (e){

				// レスポンスボディを取得する
				console.log(xhr.responseText );

			};

			// ------------------------------------------------------------
			// 「POST メソッド」「接続先 URL」を指定
			// ------------------------------------------------------------
			xhr.open("POST" , "http://example.com/cgi-bin/upload.cgi?type=json");

			// ------------------------------------------------------------
			// 「送信データに FormData を指定」「XHR 通信を開始する」
			// ------------------------------------------------------------
			xhr.send(form_data);

		});

	})();
    //-->
    </script>

  </body>
</html>
 

■フォームを利用しないアップロードについて


■空の FormData オブジェクトを作成する
 
FormData コンストラクタを使って、空の FormData オブジェクトを作成します。
 
引数は、省略します。
 
■送信するデータを追加する
 
送信予定のデータを追加するには、append() メソッドを使用します。
 
Drag and Drop」を使って入手したファイルを、送信内容に含める事もできます。
 
■シンプルな送信例
 
XMLHttpRequest と FormData のみを使った送受信

// 匿名関数を即時実行
(function(){

	// ------------------------------------------------------------
	// サポートチェック
	// ------------------------------------------------------------
	if(!(window.FormData)) return;

	// ------------------------------------------------------------
	// 空の FormData オブジェクトを作成する
	// ------------------------------------------------------------
	var form_data = new FormData();

	// ------------------------------------------------------------
	// 送信データを追加する
	// ------------------------------------------------------------
	form_data.append( "name_a" , "value_a" );
	form_data.append( "name_b" , "value_b" );
	form_data.append( "name_c" , "value_c" );

	// ------------------------------------------------------------
	// XMLHttpRequest オブジェクトを作成
	// ------------------------------------------------------------
	var xhr = new XMLHttpRequest();

	// ------------------------------------------------------------
	// XHR 通信に成功すると実行されるイベント
	// ------------------------------------------------------------
	xhr.onload = function (e){

		// レスポンスボディを取得する
		console.log(xhr.responseText );

	};

	// ------------------------------------------------------------
	// 「POST メソッド」「接続先 URL」を指定
	// ------------------------------------------------------------
	xhr.open("POST" , "http://example.com/cgi-bin/upload.cgi?type=json");

	// ------------------------------------------------------------
	// 「送信データに FormData を指定」「XHR 通信を開始する」
	// ------------------------------------------------------------
	xhr.send(form_data);

})();
 
■ファイルを含めた送信例
 
ドラッグアンドドロップについては、こちらで解説しています。
 
「ファイル選択コントロール」「Drag and Drop」を使って、ファイルをアップロードする

<html>
  <body>

    --- ドラッグアンドドロップ ---<br>
    <div id="drop_area" style="width:400px; height:300px; background:#ccf;" ></div>
    <p></p>

    --- ファイル選択コントロール ---<br>
    <input type="file" id="input_file" multiple >
    <p></p>

    --- 送信用ボタン ---<br>
    <input type="button" value="送信" id="input_button" >
    <p></p>

    <script type="text/javascript">
    <!--
	// 匿名関数を即時実行
	(function(){

		// ------------------------------------------------------------
		// サポートチェック
		// ------------------------------------------------------------
		if(!(window.addEventListener)) return;
		if(!(window.File)) return;
		if(!(window.FormData)) return;

		// ------------------------------------------------------------
		// ドラッグアンドドロップで受け取るファイルのリスト
		// ------------------------------------------------------------
		var drop_file_list = new Array();

		// ------------------------------------------------------------
		// 各要素を取得する
		// ------------------------------------------------------------
		// "drop_area" という ID 属性のエレメントを取得する
		var drop_area = document.getElementById("drop_area");

		// "input_file" という ID 属性のエレメントを取得する
		var input_file = document.getElementById("input_file");

		// "input_button" という ID 属性のエレメントを取得する
		var input_button = document.getElementById("input_button");

		// ------------------------------------------------------------
		// ドラッグ操作中に実行されるイベント(マウスカーソルが要素内に滞在中)
		// ------------------------------------------------------------
		drop_area.addEventListener("dragover" , function (e){
			// ドロップを許可し受け入れを表明
			e.preventDefault();
		});

		// ------------------------------------------------------------
		// ドロップ時に実行されるイベント
		// ------------------------------------------------------------
		drop_area.addEventListener("drop" , function (e){

			// ------------------------------------------------------------
			// デフォルトのドロップ機能を無効化する
			// ------------------------------------------------------------
			e.preventDefault();

			// ------------------------------------------------------------
			// DataTransfer オブジェクトを取得する
			// ------------------------------------------------------------
			var data_transfer = e.dataTransfer;

			// ------------------------------------------------------------
			// ファイルリストを取得する
			// ------------------------------------------------------------
			var file_list = data_transfer.files;
			if(file_list){
				var i;
				var num = file_list.length;
				for(i=0;i < num;i++){
					// File オブジェクトを取得する
					var file = file_list[i];

					// リストに追加
					drop_file_list.push(file);
				}
			}
		});

		// ------------------------------------------------------------
		// ボタンをクリックした時に実行されるイベント
		// ------------------------------------------------------------
		input_button.addEventListener("click" , function(e){

			// ------------------------------------------------------------
			// 空の FormData オブジェクトを作成する
			// ------------------------------------------------------------
			var form_data = new FormData();

			// ------------------------------------------------------------
			// ファイル選択コントロールからファイルリストを取得する
			// ------------------------------------------------------------
			var file_list = input_file.files;
			if(file_list){
				var i;
				var num = file_list.length;
				for(i=0;i < num;i++){
					// File オブジェクトを取得する
					var file = file_list[i];

					// ファイル名を取得する
					var file_name = file.name;

					// 送信データを追加する
					form_data.append( file_name , file );
				}
			}

			// ------------------------------------------------------------
			// ドラッグアンドドロップで受け取ったファイルリスト
			// ------------------------------------------------------------
			var i;
			var num = drop_file_list.length;
			for(i=0;i < num;i++){
				// File オブジェクトを取得する
				var file = drop_file_list[i];

				// ファイル名を取得する
				var file_name = file.name;

				// 送信データを追加する
				form_data.append( file_name , file );
			}

			// ------------------------------------------------------------
			// XMLHttpRequest オブジェクトを作成
			// ------------------------------------------------------------
			var xhr = new XMLHttpRequest();

			// ------------------------------------------------------------
			// XHR 通信に成功すると実行されるイベント
			// ------------------------------------------------------------
			xhr.onload = function (e){

				// レスポンスボディを取得する
				console.log(xhr.responseText );

			};

			// ------------------------------------------------------------
			// 「POST メソッド」「接続先 URL」を指定
			// ------------------------------------------------------------
			xhr.open("POST" , "http://example.com/cgi-bin/upload.cgi?type=json");

			// ------------------------------------------------------------
			// 「送信データに FormData を指定」「XHR 通信を開始する」
			// ------------------------------------------------------------
			xhr.send(form_data);

		});

	})();
    //-->
    </script>

  </body>
</html>
 

■ XHR 送受信の進捗状況を調べる

 
■送信中の進捗状況を調べる(アップロード中)
 
送信中の進捗状況を調べる方法については、こちらで解説しています。
 
■受信中の進捗状況を調べる
 
受信中の進捗状況を調べる方法については、こちらで解説しています。
 

■送信するファイルの情報を取得する

 
ファイル名や、ファイルの種類、ファイルのサイズを取得する事ができます。
 
File のプロパティについては、こちらで解説しています。
 


 

サーバー側の処理について

 


■CGI 側の処理について


CGI 側でファイルのアップロードを受け取る方法として、以下のスクリプトを使用してみます。
 
結果を出力する方法は、こちらで解説しています。
 
クライアントからは、「multipart/form-data」形式で、データが送信されるものとします。
 
 

■Perl を使用する

 
Perl を利用して、ファイルの受信処理を行ってみます。
 

■CGIモジュールを読み込む

 
CGIモジュールを使ってデータを受信します。 まず、CGI モジュールを読み込みます。
 
CGI モジュールを読み込む

#!/usr/local/bin/perl

# CGI モジュールを読み込む
use CGI;
 

■アップロードサイズの上限バイト数を設定する


$CGI::POST_MAX にて、アップロードサイズの上限バイト数を設定できます。
 
無制限にせずに、何らかの上限値を決めておくのがよさそうです。次に解説する 「CGI オブジェクトを作成する」よりも前に記述します。
 
アップロードサイズの上限バイト数を設定する

# アップロードサイズの上限バイト数
$CGI::POST_MAX = 1024 * 1024 *10;
 

■CGI オブジェクトを作成する


new 演算子を使って、CGI オブジェクトを作成します。
 
CGI オブジェクトを作成する

# CGI オブジェクトを作成する
$query = new CGI;
 

■フォーム内のパラメータを取得する


param() メソッドを使用するとフォーム内のコントロールの値を取り出すことができます。
 
引数に、「コントロールの name 属性で指定した名前」をセットします。
 
複数の同名コントロールがある場合、配列として値を取り出す事ができます。
 
フォームの例(HTML)

<form>

	<input type="text" name="input_text0" ><br>
	<input type="text" name="input_text1" ><br>

	<input type="checkbox" name="input_checkbox" value="aaa">AAA<br>
	<input type="checkbox" name="input_checkbox" value="bbb">BBB<br>
	<input type="checkbox" name="input_checkbox" value="ccc">CCC<br>

	<input type="radio" name="input_radio" value="000">000
	<input type="radio" name="input_radio" value="111">111

</form>
 
コントロールの名前から値を取得する(CGI)

#!/usr/local/bin/perl

# CGI モジュールを読み込む
use CGI;

# アップロードサイズの上限バイト数
$CGI::POST_MAX = 1024 * 1024 *10;

# CGI オブジェクトを作成する
$query = new CGI;

# param() メソッドを使って、名前を指定して値を取得する
$input_text0 = $query->param("input_text0");
$input_text1 = $query->param("input_text1");
$input_radio = $query->param("input_radio");

# 同名のパラメータがある場合、配列として取得する
@input_checkbox = $query->param("input_checkbox");
 

■アップロードされたファイルのハンドルを取得する


アップロードされたファイルは、サーバーの一時的な作業場所に保存されています。
 
CGI の実行が終了すると消滅します。
 
upload() メソッドを使用するとファイルハンドルを取得することができます。
 
引数に、「コントロールの name 属性で指定した名前」をセットします。
 
複数の同名のコントロールがある場合や、ファイル選択用コントロールを複数選択(multiple)にした場合、配列としてファイルハンドルを取り出す事ができます。
 
フォームの例(HTML)

<form>

	<input type="file" name="input_file0" ><br>
	<input type="file" name="input_file1" ><br>

	<input type="file" name="input_files" ><br>
	<input type="file" name="input_files" ><br>
	<input type="file" name="input_files" multiple>

</form>
 
コントロールの名前からファイルハンドルを取得する(CGI)

#!/usr/local/bin/perl

# CGI モジュールを読み込む
use CGI;

# アップロードサイズの上限バイト数
$CGI::POST_MAX = 1024 * 1024 *10;

# CGI オブジェクトを作成する
$query = new CGI;

# upload() メソッドを使って、名前を指定してファイルハンドルを取得する
$file_handle0 = $query->upload("input_file0");
$file_handle1 = $query->upload("input_file1");

# 同名のパラメータがある場合、配列として取得する
@file_handles = $query->upload("input_files");
 
何らかの原因でアップロードに失敗している場合は、未定義値が得られます。
 
upload() メソッドを呼び出した直後に失敗しているか確認する例です。
 
コントロールの名前 "input_file" からファイルハンドルを取得する(CGI)

$file_handle = $query->upload("input_file");
if (!$file_handle && $query->cgi_error) {
	# エラー
}
 

■アップロードされたファイルの MIME タイプを取得する


uploadInfo() メソッドを使用すると「アップロード情報」が格納された連想配列のリファレンスを取得できます。
 
uploadInfo() メソッドの引数に、ファイル名かファイルハンドルをセットします。
 
以下の要素があります。
 
要素名 解説
Content-Type アップロードされたファイルの MIME タイプ
 
コントロールの名前 "input_file" からファイルの MIME タイプを取得する(CGI)

#!/usr/local/bin/perl

# CGI モジュールを読み込む
use CGI;

# アップロードサイズの上限バイト数
$CGI::POST_MAX = 1024 * 1024 *10;

# CGI オブジェクトを作成する
$query = new CGI;

# upload() メソッドを使って、名前を指定してファイルハンドルを取得する
$file_handle = $query->upload("input_file");

# アップロード情報を取得する
$upload_info = $query->uploadInfo($file_handle);
$mime_type = $upload_info->{"Content-Type"};
 

■アップロードされたファイル名を取得する


ファイルハンドルはそのままファイル名として使用できます。
 
ブラウザによっては、ユーザーがアップロードを試みたローカルのディレクトリパスまで含まれていることがあります。 そこで、正規表現を使って最後のファイル名だけ取り出します。
 
取得例です。
 
ファイル名と拡張子を取得する

#!/usr/local/bin/perl

# CGI モジュールを読み込む
use CGI;

# アップロードサイズの上限バイト数
$CGI::POST_MAX = 1024 * 1024 *10;

# CGI オブジェクトを作成する
$query = new CGI;

# upload() メソッドを使って、名前を指定してファイルハンドルを取得する
$file_handle = $query->upload("input_file");

# ファイル名を取得する
$file_name = StringGetFileName($file_handle);

# 拡張子を取得する
$file_ext = StringGetFileExtension($file_name);


#// -----------------------------------------------------
#// 文字列から最後のファイル名を取得する
#// -----------------------------------------------------
sub StringGetFileName(){
	my ($string) = @_;
	return ($string =~ /([^\\\/:]+)$/) ? $1 : $string;
}

#// -----------------------------------------------------
#// 文字列から拡張子を取得する(なければ undef)
#// -----------------------------------------------------
sub StringGetFileExtension(){
	my ($string) = @_;
	$string = ($string =~ /([^\\\/:]+)$/) ? $1 : $string;
	return ($string =~ /([^\.]+)$/) ? $1 : undef;
}
 

■アップロードされたファイルをサーバーディレクトリ内にコピーする


copy() 関数を使用するとファイルをサーバーディレクトリにコピーすることができます。
 
第01引数にファイルハンドル、
 
第02引数に保存したいサーバー上のファイルパスを指定します。
 
ユーザーが付けた名前をそのまま使用してサーバに保存するのは危険です。
 
外部から「全角名のファイル」や「HTTPサーバーの設定ファイル」や「CGI ファイル」の格納を許すことになります。
 
安全と判断できる拡張子だけコピーを許したり、ファイル名は管理しやすいようにリネームするなどの対策が必要となります。
 
アップロードされたファイルを「現在の時間 + 拡張子」で保存する
(注意.排他処理を考慮していません。このままでは多人数同時アクセスされるとファイルが上書きされる事があります)

#!/usr/local/bin/perl

# 各モジュールを読み込む
use CGI;
use File::Copy;

# アップロードサイズの上限バイト数
$CGI::POST_MAX = 1024 * 1024 *10;

# CGI オブジェクトを作成する
$query = new CGI;

# upload() メソッドを使って、名前を指定してファイルハンドルを取得する
$file_handle = $query->upload("input_file");

# 拡張子を取得する
$file_ext = StringGetFileExtension($file_handle);

# アップロード可能な拡張子であるか調べる
if(FileExtensionGetAllowUpload($file_ext)){

	# 現在の時間を取得する
	my $time_now = time();

	# 保存先のファイルパスを生成する(実戦運用する場合、排他処理を考慮して保存先のファイル名を生成する必要があります)
	$file_name_new = "./" . $time_now . "." . $file_ext;
	
	# ファイルのコピーを行う
	copy ($file_handle, $file_name_new);
}



#// -----------------------------------------------------
#// 文字列から拡張子を取得する(なければ undef)
#// -----------------------------------------------------
sub StringGetFileExtension(){
	my ($string) = @_;
	$string = ($string =~ /([^\\\/:]+)$/) ? $1 : $string;
	return ($string =~ /([^\.]+)$/) ? $1 : undef;
}


#// -----------------------------------------------------
#// 拡張子からアップロードを許すか調べる
#// -----------------------------------------------------
sub FileExtensionGetAllowUpload(){
	my ($ext) = @_;
	# アップロードを許可したい拡張子があればここに追加
	my @allow_ext = ("bmp","gif","jpg","jpeg","png","zip");

	foreach my $v ( @allow_ext ){
		if ($v eq $ext){
			return 1;
		}
	}

	return 0;
}
 
 

■PHP を使用する

 
PHP を利用して、ファイルの受信処理を行ってみます。
 

■アップロードされたファイルの連想配列を取得する


アップロードされたファイルは、サーバーの一時的な作業場所に保存されています。
 
PHP の実行が終了すると消滅します。
 
$_FILES 連想配列に、アップロードされたファイルの情報がまとめて格納されています。
 
まずはここから、「コントロールの name 属性で指定した名前」をキーにして、個別に「ファイルの情報が格納された連想配列」を取り出します。
 
複数の同名のコントロールがある場合、
 
名前の最後尾に、"[]" を付ける必要があります。これで配列として取り出せるようになります。
 
取得を試みると1つの「ファイルの情報が格納された連想配列」を取得することができます。(複数の連想配列を取得できるのではなく、1つの連想配列の各要素がそれぞれ配列となっています)
 
フォームの例(HTML)

<form>

	<input type="file" name="input_file0" ><br>
	<input type="file" name="input_file1" ><br>

	<input type="file" name="input_files[]" ><br>
	<input type="file" name="input_files[]" ><br>
	<input type="file" name="input_files[]" multiple>

</form>
 
コントロールの名前からファイルハンドルを取得する(CGI)

<?php

	# Content-type を出力
	header("Content-type:text/html");
	
	# 名前を指定してファイル情報を取得する
	$input_file0 = $_FILES["input_file0"];
	$input_file1 = $_FILES["input_file1"];

	# 同名のパラメータがある場合、1つの連想配列を取得できる(この時点では配列ではない)
	$input_files = $_FILES["input_files"];

?>
 
何らかの原因でアップロードに失敗している場合は、NULL となります。
 

■アップロードされたファイルの情報を取得する


「ファイルの情報が格納された連想配列」には、以下の要素があります。
 
複数の同名のコントロールがある場合は、各要素の中身が配列となっています。
 
要素名 解説
name アップロードされたファイルの名前
type アップロードされたファイルの MIME タイプ
size アップロードされたファイルのサイズ
tmp_name アップロードされたファイルが格納されている一時的なパス名
error エラーが無ければ 0 、エラーがあれば 0 以外の数値
 
コントロールの名前 "input_file" からファイルの MIME タイプを取得する(CGI)

<?php

	# Content-type を出力
	header("Content-type:text/plain");
	
	# 名前を指定してファイル情報を取得する
	$input_file = $_FILES["input_file"];

	echo "name:" . $input_file["name"] . "\n";
	echo "type:" . $input_file["type"] . "\n";
	echo "size:" . $input_file["size"] . "\n";
	echo "tmp_name:" . $input_file["tmp_name"] . "\n";
	echo "error:" . $input_file["error"] . "\n";

?>
 

■アップロードされたファイルをサーバーディレクトリ内に移動する


move_uploaded_file() 関数を使用すると「一時的な作業場所にあるファイル」を「正式なサーバーディレクトリ内」に移動することができます。
 
第01引数に "tmp_name" で取得したファイルパス
 
第02引数に保存したいサーバー上のファイルパスを指定します。
 
成功すれば TRUE 、失敗すれば FALSE が返ります。
 
移動先のフォルダに「書き込みパーミッション」がない場合、失敗するようです。
 
ユーザーが付けた名前をそのまま使用してサーバに保存するのは危険です。
 
外部から「全角名のファイル」や「HTTPサーバーの設定ファイル」や「CGI ファイル」の格納を許すことになります。
 
安全と判断できる拡張子だけコピーを許したり、ファイル名は管理しやすいようにリネームするなどの対策が必要となります。
 
アップロードされたファイルを「現在の時間 + 拡張子」で保存する
(注意.排他処理を考慮していません。このままでは多人数同時アクセスされるとファイルが上書きされる事があります)

<?php

	# Content-type を出力
	header("Content-type:text/plain");
	
	# 名前を指定してファイル情報を取得する
	$input_file = $_FILES["input_file"];

	# 拡張子を取得する
	$file_ext = pathinfo($input_file["name"], PATHINFO_EXTENSION);

	# アップロード可能な拡張子であるか調べる
	if(FileExtensionGetAllowUpload($file_ext)){

		# 現在の時間を取得する
		$time_now = time();

		# 保存先のファイルパスを生成する(実戦運用する場合、排他処理を考慮して保存先のファイル名を生成する必要があります)
		$file_name_new = "./" . $time_now . "." . $file_ext;
	
		# ファイルの移動を行う
		move_uploaded_file ($input_file["tmp_name"], $file_name_new);
	}


	#// -----------------------------------------------------
	#// 拡張子からアップロードを許すか調べる
	#// -----------------------------------------------------
	function FileExtensionGetAllowUpload($ext){

		# アップロードを許可したい拡張子があればここに追加
		$allow_ext = array("bmp","gif","jpg","jpeg","png","zip");

		foreach($allow_ext as $v){
			if ($v === $ext){
				return 1;
			}
		}

		return 0;
	}

?>
 
 

■Ruby を使用する

 
Ruby を利用して、ファイルの受信処理を行ってみます。
 

■CGIモジュールを読み込む

 
CGIモジュールを使ってデータを受信します。 まず、CGI モジュールを読み込みます。
 
CGI モジュールを読み込む

#!/usr/local/bin/ruby

# CGI モジュールを読み込む
require "cgi"
 

■CGI オブジェクトを作成する


new メソッドを使って、CGI オブジェクトを作成します。
 
CGI オブジェクトを作成する

# CGI オブジェクトを作成する
query = CGI.new
 

■フォーム内のパラメータを取得する


コントロールの name 属性で指定した名前」をキーにしてアクセスすると、データを取得することができます。
 
複数の同名コントロールがある場合、params に対してアクセスすると配列としてデータを取得することができます。
 
文字列データである場合、「StringIO オブジェクト」が得られます。
 
「StringIO オブジェクト」から文字列を取得するには string メソッドを呼び出します。
 
フォームの例(HTML)

<form>

	<input type="text" name="input_text0" ><br>
	<input type="text" name="input_text1" ><br>

	<input type="checkbox" name="input_checkbox" value="aaa">AAA<br>
	<input type="checkbox" name="input_checkbox" value="bbb">BBB<br>
	<input type="checkbox" name="input_checkbox" value="ccc">CCC<br>

	<input type="radio" name="input_radio" value="000">000
	<input type="radio" name="input_radio" value="111">111

</form>
 
コントロールの名前から値を取得する(CGI)

#!/usr/local/bin/ruby

# CGI モジュールを読み込む
require "cgi"

# CGI オブジェクトを作成する
query = CGI.new

# 名前をキーにして StringIO オブジェクトを取得する
input_text0 = query["input_text0"]
input_text1 = query["input_text1"]
input_radio = query["input_radio"]

# 同名のパラメータがある場合、params からアクセスして配列として取得する
input_checkbox = query.params["input_checkbox"]

# Content-type を出力
print "Content-Type: text/plain\n"

# 改行のみでヘッダの終了
print "\n"

# テスト出力
print input_text0.string + "\n"
print input_text1.string + "\n"
print input_radio.string + "\n"

 

■アップロードされたファイルの情報を取得する


アップロードされたファイルは、サーバーの一時的な作業場所に保存されています。
 
CGI の実行が終了すると消滅します。
 
「フォーム内のパラメータを取得する」と同じ方法でデータを取得します。
 
ファイルデータである場合、「Tempfile オブジェクト」が得られます。
 
(送信されたデータの総サイズが、10240 バイト未満である場合、「StringIO オブジェクト」が得られますが、Tempfile オブジェクトのようにアクセスできるようです)
 
「Tempfile オブジェクト」には、以下のメソッドがあります。
 
要素名 解説
original_filename アップロードされたファイルの名前(ブラウザによってはローカルパスも含む)
size アップロードされたファイルのサイズ
content_type アップロードされたファイルの MIME タイプ
read ファイルのデータ本体
 
フォームの例(HTML)

<form>

	<input type="file" name="input_file0" ><br>
	<input type="file" name="input_file1" ><br>

	<input type="file" name="input_files" ><br>
	<input type="file" name="input_files" ><br>
	<input type="file" name="input_files" multiple>

</form>
 
コントロールの名前からファイルオブジェクトを取得する(CGI)

#!/usr/local/bin/ruby

# CGI モジュールを読み込む
require "cgi"

# CGI オブジェクトを作成する
query = CGI.new

# 名前をキーにして Tempfile オブジェクトを取得する
input_file0 = query["input_file0"]
input_file1 = query["input_file1"]

# 同名のパラメータがある場合、params からアクセスして配列として取得する
input_files = query.params["input_files"]

# Content-type を出力
print "Content-Type: text/plain\n"

# 改行のみでヘッダの終了
print "\n"

# テスト出力
print input_file0.original_filename + "\n"
print input_file0.size.to_s + "\n"
print input_file0.content_type + "\n"
 

■アップロードされたファイル名を取得する


「Tempfile オブジェクト」の original_filename メソッドからファイル名を取得できます。
 
ブラウザによっては、ユーザーがアップロードを試みたローカルのディレクトリパスまで含まれていることがあります。 そこで、正規表現を使って最後のファイル名だけ取り出します。
 
取得例です。
 
ファイル名と拡張子を取得する

#!/usr/local/bin/ruby

# CGI モジュールを読み込む
require "cgi"

#// -----------------------------------------------------
#// 文字列から最後のファイル名を取得する
#// -----------------------------------------------------
def StringGetFileName(string)
	return string.split(/(\\|\/)/)[-1]
end


#// -----------------------------------------------------
#// 文字列から拡張子を取得する(なければ nil)
#// -----------------------------------------------------
def StringGetFileExtension(string)
	string = string.split(/(\\|\/)/)[-1]
	a = string.split(/(\.)/)
	if a.length > 1 then
		return a[-1]
	end
	return nil
end


# CGI オブジェクトを作成する
query = CGI.new

# 名前をキーにして Tempfile オブジェクトを取得する
input_file = query["input_file"]

# ファイル名を取得する
file_name = StringGetFileName(input_file.original_filename)

# 拡張子を取得する
file_ext = StringGetFileExtension(file_name)


# Content-type を出力
print "Content-Type: text/plain\n"

# 改行のみでヘッダの終了
print "\n"

# テスト出力
print file_name + "\n"
print file_ext + "\n"
 

■アップロードされたファイルをサーバーディレクトリ内にコピーする


File オブジェクト を使用するとファイルをサーバーディレクトリに書きこむことができます。
 
File オブジェクトを取得するには、open 関数を使用します。
 
ユーザーが付けた名前をそのまま使用してサーバに保存するのは危険です。
 
外部から「全角名のファイル」や「HTTPサーバーの設定ファイル」や「CGI ファイル」の格納を許すことになります。
 
安全と判断できる拡張子だけコピーを許したり、ファイル名は管理しやすいようにリネームするなどの対策が必要となります。
 
アップロードされたファイルを「現在の時間 + 拡張子」で保存する
(注意.排他処理を考慮していません。このままでは多人数同時アクセスされるとファイルが上書きされる事があります)

#!/usr/local/bin/ruby

# CGI モジュールを読み込む
require "cgi"

#// -----------------------------------------------------
#// 拡張子からアップロードを許すか調べる
#// -----------------------------------------------------
def FileExtensionGetAllowUpload(ext)

	# アップロードを許可したい拡張子があればここに追加
	allow_ext = ["bmp","gif","jpg","jpeg","png","zip"]

	allow_ext.each { |v|
		if (v == ext) then
			return true
		end
	}
	return false
end


#// -----------------------------------------------------
#// 文字列から拡張子を取得する(なければ nil)
#// -----------------------------------------------------
def StringGetFileExtension(string)
	string = string.split(/(\\|\/)/)[-1]
	a = string.split(/(\.)/)
	if a.length > 1 then
		return a[-1]
	end
	return nil
end


# CGI オブジェクトを作成する
query = CGI.new

# 名前をキーにして Tempfile オブジェクトを取得する
input_file = query["input_file"]

# 拡張子を取得する
file_ext = StringGetFileExtension(input_file.original_filename)

# アップロード可能な拡張子であるか調べる
if (FileExtensionGetAllowUpload(file_ext)) then

	# 現在の時間を取得する
	time_now = Time.now.tv_sec

	# 保存先のファイルパスを生成する(実戦運用する場合、排他処理を考慮して保存先のファイル名を生成する必要があります)
	$file_name_new = "./" + time_now.to_s + "." + file_ext
	
	# File オブジェクトを取得する
	open($file_name_new, "w") {|fh|

		# バイナリモードを使用する
		fh.binmode

		# 一時的なファイルを書きだす
		fh.write(input_file.read)
	}
end
 
 

■Python を使用する

 
Python を利用して、ファイルの受信処理を行ってみます。
 

■CGIモジュールを読み込む

 
CGIモジュールを使ってデータを受信します。 まず、CGI モジュールを読み込みます。
 
CGI モジュールを読み込む

#!/usr/local/bin/python
# coding: utf-8


# ライブラリをロード
import cgi
 

■FieldStorage オブジェクトを作成する


cgi.FieldStorage() メソッドを使って、FieldStorage オブジェクトを作成します。
 
CGI オブジェクトを作成する

# FieldStorage オブジェクトを作成する
query = cgi.FieldStorage()
 

■フォーム内のパラメータを取得する


getvalue() メソッドを使用するとフォーム内のコントロールの値を取り出すことができます。
 
第01引数に、「コントロールの name 属性で指定した名前」をセットします。
 
第02引数(省略可)に値をセットしておくと、パラメータが存在しなかった場合にセットした値をそのまま返します。
 
複数の同名コントロールがある場合、getlist() メソッドを使用すると、配列として値を取り出す事ができます。
 
引数に、「コントロールの name 属性で指定した名前」をセットします。
 
フォームの例(HTML)

<form>

	<input type="text" name="input_text0" ><br>
	<input type="text" name="input_text1" ><br>

	<input type="checkbox" name="input_checkbox" value="aaa">AAA<br>
	<input type="checkbox" name="input_checkbox" value="bbb">BBB<br>
	<input type="checkbox" name="input_checkbox" value="ccc">CCC<br>

	<input type="radio" name="input_radio" value="000">000
	<input type="radio" name="input_radio" value="111">111

</form>
 
コントロールの名前から値を取得する(CGI)

#!/usr/local/bin/python
# coding: utf-8


# ライブラリをロード
import cgi

# FieldStorage オブジェクトを作成する
query = cgi.FieldStorage()

# getvalue メソッドを使って名前から値を取得する
input_text0 = query.getvalue("input_text0")
input_text1 = query.getvalue("input_text1")
input_radio = query.getvalue("input_radio")

# 同名のパラメータがある場合、getlist メソッドを使って配列として取得する
input_checkbox = query.getlist("input_checkbox")
 

■アップロードされたファイルの情報を取得する


アップロードされたファイルは、サーバーの一時的な作業場所に保存されています。
 
CGI の実行が終了すると消滅します。
 
「FieldStorage オブジェクト」の has_key() メソッドを使用するとその名前のパラメータが存在するか調べることができます。
 
引数に、「コントロールの name 属性で指定した名前」をセットします。
 
「FieldStorage オブジェクト」に対して「コントロールの name 属性で指定した名前」をキーにしてアクセスすると、「Field オブジェクト」を取得できます。
 
複数の同名コントロールがある場合、配列として「Field オブジェクト」を取得できます。
 
ファイルデータであった場合、以下の属性からファイル情報を取得できます。
 
要素名 解説
filename アップロードされたファイルの名前(ブラウザによってはローカルパスも含む)
type アップロードされたファイルの MIME タイプ
file TemporaryFile オブジェクト
 
フォームの例(HTML)

<form>

	<input type="file" name="input_file0" ><br>
	<input type="file" name="input_file1" ><br>

	<input type="file" name="input_files" ><br>
	<input type="file" name="input_files" ><br>
	<input type="file" name="input_files" multiple>

</form>
 
コントロールの名前からField オブジェクトを取得する(CGI)

#!/usr/local/bin/python
# coding: utf-8


# ライブラリをロード
import cgi

# FieldStorage オブジェクトを作成する
query = cgi.FieldStorage()

# 名前から Field オブジェクトを取得する
input_file0 = query["input_file0"]
input_file1 = query["input_file1"]

# 同名のパラメータがある場合、配列として取得する
input_files = query["input_files"]
 

■アップロードされたファイル名を取得する


「Field オブジェクト」の filename 属性からファイル名を取得できます。
 
ブラウザによっては、ユーザーがアップロードを試みたローカルのディレクトリパスまで含まれていることがあります。 そこで、正規表現を使って最後のファイル名だけ取り出します。
 
取得例です。
 
ファイル名と拡張子を取得する

#!/usr/local/bin/python
# coding: utf-8


# ライブラリをロード
import cgi
import re


#// -----------------------------------------------------
#// 文字列から最後のファイル名を取得する
#// -----------------------------------------------------
def StringGetFileName(string) :
	return re.split('[\\\/]',string)[-1]


#// -----------------------------------------------------
#// 文字列から拡張子を取得する(なければ None)
#// -----------------------------------------------------
def StringGetFileExtension(string) :
	string = re.split('[\\\/]',string)[-1]
	a = re.split('\.',string)
	if (len(a) > 1) :
		return a[-1]
	return None


# FieldStorage オブジェクトを作成する
query = cgi.FieldStorage()

# Field オブジェクトが存在するか調べる
if (query.has_key("input_file")) :

	# 名前から Field オブジェクトを取得する
	input_file = query["input_file"]

	# ファイル名を取得する
	file_name = StringGetFileName(input_file.filename)

	# 拡張子を取得する
	file_ext = StringGetFileExtension(file_name)
 

■アップロードされたファイルをサーバーディレクトリ内にコピーする


「Field オブジェクト」の file 属性から TemporaryFile オブジェクトを取得できます。
 
TemporaryFile オブジェクトの read メソッドを使用すると、ファイルのデータ本体を取得することができます。
 
file 関数を使用するとファイルを出力することができます。
 
ユーザーが付けた名前をそのまま使用してサーバに保存するのは危険です。
 
外部から「全角名のファイル」や「HTTPサーバーの設定ファイル」や「CGI ファイル」の格納を許すことになります。
 
安全と判断できる拡張子だけコピーを許したり、ファイル名は管理しやすいようにリネームするなどの対策が必要となります。
 
アップロードされたファイルを「現在の時間 + 拡張子」で保存する
(注意.排他処理を考慮していません。このままでは多人数同時アクセスされるとファイルが上書きされる事があります)

#!/usr/local/bin/python
# coding: utf-8


# ライブラリをロード
import cgi
import re
import time


#// -----------------------------------------------------
#// 拡張子からアップロードを許すか調べる
#// -----------------------------------------------------
def FileExtensionGetAllowUpload(ext) :

	# アップロードを許可したい拡張子があればここに追加
	allow_ext = ["bmp","gif","jpg","jpeg","png","zip"]

	for v in allow_ext :
		if (v == ext) :
			return True
	return False


#// -----------------------------------------------------
#// 文字列から拡張子を取得する(なければ None)
#// -----------------------------------------------------
def StringGetFileExtension(string) :
	string = re.split('[\\\/]',string)[-1]
	a = re.split('\.',string)
	if (len(a) > 1) :
		return a[-1]
	return None


# FieldStorage オブジェクトを作成する
query = cgi.FieldStorage()

# Field オブジェクトが存在するか調べる
if (query.has_key("input_file")) :

	# 名前から Field オブジェクトを取得する
	input_file = query["input_file"]

	# TemporaryFile オブジェクトを所有しているか調べる
	if (input_file.file) :

		# 拡張子を取得する
		file_ext = StringGetFileExtension(input_file.filename)

		# アップロード可能な拡張子であるか調べる
		if (FileExtensionGetAllowUpload(file_ext)) :

			# 現在の時間を取得する
			time_now = int(time.time());

			# 保存先のファイルパスを生成する(実戦運用する場合、排他処理を考慮して保存先のファイル名を生成する必要があります)
			file_name_new = "./" + str(time_now) + "." + file_ext

			# 書きこみ属性、バイナリモードでファイルを開く
			fh = file(file_name_new, 'wb')

			# アップロードされたファイルを読み込んでそのまま書き出し
			fh.write(input_file.file.read())

			# ファイルを閉じる
			fh.close()