fc2ブログ

htmlconvertのテスト





C:\xampp\htdocs\test13\3-4-A.php.html











<?php
$kotoba = "はじめまして";
echo $kotoba;
?>



スポンサーサイト



【PHP】PHP復習三十日目

セッションの管理

■セッション概要

Cookieでもクライアント(ブラウザ、またはユーザ)を識別することが可能ではあるが、CookieはかなりHTTPの仕組みに近い機能であるため、スクリプトからは少々使いづらい側面がある。
つまり、HTTPで定められたCookieの枠組みを意識して有効期限やデータ形式を設定しなければならず、セキュリティも意識しなければならない。
Cookieに設定するデータはスクリプト中の変数であることがほとんどなので、よりスクリプトの構造に近い形、つまり変数を特定のクライアントに結びつける形で利用できることが望まれる。
セッションはこれらを踏まえてスクリプトからクライアント識別を使いやすくするための機能である。
そのため、セッションでは「今アクセスしているクライアントに変数v登録する」といったスタイルで使えるようになっている。
セッションは通常基礎技術としてCookieを利用して実現する。

■セッション操作の流れ

ina06_20110811235252.jpg

セッションは全体として、上記の図のような流れで操作する。
この全てが一つのスクリプト(ページ)中になくても構わない。
むしろ複数のスクリプトをまたいで、変数を使用するのがセッションの基本的な考えなので、セッション変数を設定したスクリプトとセッション変数を削除するスクリプトは別のものになることのほうが多い。
ただし、どのスクリプトでもセッションを使う前にsession_start()関数を呼びだす必要がある。

boolsession_start()
セッション機能を開始する


session_start()関数をコールした後の大まかなフローは上記の図となる。

session_start()関数が実行されると、「PHPSESSIONID」という名前のCookieが自動的に設定される。
値はユニークなIDでこれをセッションIDと呼ぶ。
そして、セッションが開始された後は、定義済み変数$_SESSIONをリクエストをまたいで使用できる変数群(これをセッションデータと呼ぶ)として利用可能になる。$_SESSIONは他の定義済み変数と同じく配列となっており、複数の変数を格納できる。
このようにセッション機能はクライアント側に保存されてセッションIDとサーバ側に保存されたセッションデータを紐付けるするものである。
これによりショッピングカートの中身がページをまたいで保持できるようになる。
セッションデータの読み書きは、次のような通常の配列にアクセスするコードで構わない。

$_SESSION['v'] = a;
echo "セッションの変数vは".$_SESSION['v']."です";

また、セッションデータの削除も通常の配列要素を削除する場合と同じで、unset()関数などが利用できる。

●URLパターン
前回のCookieのエントリにも少し書いたが、Cookieはクライアントによって、サポートの有無やサポートレベルが異なる。
クライアントの識別機能はwebアプリケーションでとても重要な機能なので、Cookieが使えないクライアントに対しては識別ができないというのは、困る。(携帯電話のブラウザの一部がこれに相当する)
そのため、Cookieサポートしていないクライアントでもクライアントの識別を可能にするために、PHPではURLパラメータにセッションのIDを埋め込む方法もサポートしている。
URLを用いる場合は「php.ini」の「session.use_cookies」ディレクティブをFALSE(または0)にする。しかし、URLは履歴に残る可能性があるため、セキュリティの理由からこの方法はお勧めできない。
Cookieによってセッションを使う場合は、PHPがセッションに対して自動生成したID値しか設定しないので、セキュリティも心配が減り、一意のIDを生成する作業も考えずに済む。

■セッションの使用例

前述したように、セッションはクライアントと変数を紐付けする機能なので、セッションデータ自体は$_SESSIONに集約されている。
まず、セッション関数を使った簡単なサンプルを示す。


<?php
#セッション開始
session_start();
if(isset($_SESSION['visited'])){
$visited = $_SESSION['visited'];
}else {
$_SESSION['visited'] = date('Y-m-d H:i:s e');
}
?>

<
html>
<
head><title>セッション</title></head>
<
body>
<
h3>セッション</h3>
<
div style = "text-align:right;">
現在時刻<?=date('Y-m-d H:i:s e')?>
<
/div>

<
p>
過去の訪問記録は
<?=isset($visited) ? $visited : "[NO SESSION]"?>
です
</p>

<
/body>
<
/html>




初回のアクセス
ina07_20110811235420.jpg

二回目のアクセス
ina08_20110811235507.jpg

このサンプルは、セッションデータを持っているか判定して、持っていなければ初回アクセスなので、現在の日時をセッションに登録する。
セッションデータを持っていればそれを表示する。

Cookieの一覧の確認
//図挿入
ina09.jpg
ina09_20110811235541.jpg


■セッションデータの削除

webアプリケーションの動作上の区切り、たとえばログアウトやショッピングの精算のタイミングでセッションデータは削除しておくべきである。
削除するのはクライアントに保存されているセッションIDのCookie、サーバのディスク上に保存されているセッションデータ。
session_destroy()関数は、セッションを用いるページ群の最後に、全てのセッションデータを破棄する目的で用いる。
しかし、この関数はCookieを削除せずセッションデータも削除しない。
セッションの保存に使ったファイルを削除するだけの関数だが、手順を間違えてCookieや$_SESSIONなどのデータが残っているとファイルを削除しない。サーバ上にゴミファイルが残らないように注意。

boolseeeion_destroy()
セッション管理に用いている内部データを破棄する。


以下のコードはsession_destroy()関数を用いてセッションをクリアする。


<?php
$_SESSION =
array();

if(isset($_COOKIE[session_name()])){
setcookie(session_name(),'',time() - 3600,'/');
}

#セッション開始
session_start();
$destroyed =
session_destroy();

?>

<
html>
<
head><title>セッションクリア</title></head>
<
body>
<
h3>session_destroy(セッションのクリア)</h3>
<?php
//セッション削除が成功した場合
if($destroyed){
echo '成功';
}else{
echo '削除失敗';
}

?>

<
/body>
<
/html>




出力結果は以下の通り
ina10_20110811235626.jpg

このソースの冒頭部にあるコードがセッションクリアのためのコードである。
session_name()関数は、セッションをCookie上で使っているときの固有の関数である。

stringsession_name()
セッションにCookieを使っている場合、$_SESSIONが関連付けられているCookieの名前を返す。


この例では、「PHPSESSID」を返すので、直接このCookie名を指定しても構わないが、セッションIDを保存するデフォルトのCookie名はphp.iniの設定により、変更可能なので、この関数を使用することをお勧めする。
その後、セッションを開始した上で、session_destroy()関数を呼びだす。
session_destroy関数は問題なく削除できたらTRUEを返す。

【PHP】PHP復習二十九日目

Cookieの使い方

Cookieとは、サーバからクライアントに送信できるデータのことである。
Cookieを受け取ったクライアントはこのデータを保存して、以後、同一サイトにリクエストするときにこのデータも送信するようになる。
これは、サーバからクライアントを識別する唯一の機構でwebアプリケーションでは、重要な役割を持つ。

■Cookieの基礎

このエントリでは、CookieをPHPから扱う方法を説明する。
まず最初にCookieについてまとめておく。
Cookieとは、サーバからクライアント(ブラウザ)に送信するデータである。
ブラウザは受け取ったCookieをサーバと関連付けて永続化(ファイルとして保存する)などする。
そして、それ以降に同じサーバにリクエストを送信する際に、該当データ付きで、送信するようになる。
サーバは既にCookieを送信してくるクライアントには、新たにCookieを送信することはない。
これでサーバが毎回ユニークな値を送信すれば、その値によってクライアントを識別できる。

ina01_20110811175914.jpg

基本的なHTTPでは、リクエストごとにTCP接続を新たに作りなおすため、サーバはリクエストを受信するごとに個別の処理として動作する。
仮にwebアプリケーションとして連続した処理であってもである。
これを簡単に説明すると、「基本的なHTTP」だけでは、ショッピングサイトで商品を次々とカートにいれていく処理が実現できないということを意味している。
なぜなら、カートに商品を入れる操作に一回につきリクエストが一回実行されるので、商品を入れるたびにショッピングサイトに入りなおしていることになる。
ユーザが二つ目の商品を選んでいるつもりでも、サーバからはそれが「先ほどのつづき」であることを認識できない。
そのため、サーバでは毎回新規とみなす以外に方法がない。
これでは、webアプリケーションが作りにくいので、Cookieという仕組みが導入された。
この機構を用いると、サーバがクライアントを識別するためのIDを割り振ることができるようになる。
さきほど説明したように、サーバからクライアント固有のデータを送信すれば、それ以降のリクエストには必ずそのデータが送信されるからである。
サーバ側での、処理だけに注目すると次のようになる。
まずスクリプトはリクエストを受けるたびに必ずCookieの存在をチェックする。もしなければ、そのクライアント専用のID値を生成してレスポンスにつけるようにする。これは、webアプリケーションによっては、ログインページで行うこともあるだろう。
IDは生成されるたびに異なる値になるが、接続している間は維持される。
この場合、IDが同じならそのユーザであることが保証されることが重要である。
ID値を生成したページ以外のスクリプトでも、もしCookieがあれば、その後の操作は全てそのIDに関連付けて管理できる。
ショッピングサイトであれば、カートに商品を入れる操作のたびに、IDと関連付けてカートの中身を追加・削除していくことになるだろう。
ここで、CookieのIDを生成したスクリプト以外のページでも、接続が継続している間はずっとIDが生きていることが重要である。
ログアウト処理やショッピング精算処理のように、サイトによっては操作の区切りがあるかもしれない。
そのタイミングでCookieを削除することもできる。
これにより、ユーザとID値の関係は破棄される。空の文字列を渡すことで、Cookieを削除すると、そのレスポンスを受け取ったクライアントは、ローカルのハードディスクからファイルを削除するなどする。
それ以降のリクエストにはCookieは付かない。
Cookieを試す上で、注意すべきは、スクリプトからみたCookieのサイクルとクライアント(ブラウザ)からみたCookieのサイクルが一致しない点である。
初回リクエストにはCookieがついていないので、「Cookieがない状態」でのレスポンスを返す。そのため、ブラウザからみたらCookieが動作していないように見える。

■Cookieの有効期限

クライアントからCookieを削除するもう一つの方法として、有効期限を設定することもできる。
このようにしておくと、特に明示的に削除処理を行わなくてもいいようになる。
webアプリケーションの場合、ブラウザを終了させてもサーバ側では、それを検知することはできない。
しかし、Cookieはこれまでに説明したように、クライアントを識別するために用いるので、セキュリティの一部として重要な意味を持つことが多い。仮に、クライアントマシンがネットカフェのように、複数のユーザによって利用されるマシンだと、Cookieがいつまでもマシンに保存されているのは望ましくない。
そのため、Cookieは原則として有効期限を設けておくべきである。
期間の長短は、webアプリケーションの使われ方から判断することになる。
不特定多数のユーザがログインして使う、アプリケーションなら10分程度に短くする。
特定少数のユーザがログインせずに使うようなら、長めに設定しておいてもいいかも知れない。


■Cookieに保存できるデータ

Cookieに設定できるデータの種類は問わないが、いくつかの制約がある。
まず、HTTPのヘッダとしてやりとりできる都合上、テキストである必要がある。
バイナリを送信したいのであれば、テキストに変換しなくてはならない。
PHPでは、この変換を暗黙のうちに行ってくれるが、暗黙の変換を行わず自分でコントロールしたい場合は「生」のまま扱う関数を使用する。
またHTTPのヘッダなので、ネットワークの覗き見に遭う可能性がある。保護すべきデータは素のまま送信するわけにはいかない。
さらにCookieとして使えるデータの量は、一般に小容量である。これらの制約から多くの場合は、プログラムでデータをそのままCookieに設定することはせず、それらを検索するために使うクライアント識別値だけをCookieに設定する。
逆にいえば、Cookieを使う場合は、そのようなクライアントの識別の方法も考えて置かなければならないということである。
ログインするアプリケーションであれば、DBにもっているユーザーの主キーを使うという方法もある。

■Cookieを利用するための関数


Cookieに関連する関数は次の通り多くはない。
多くの場合、setCookie()関数だけで十分。
このエントリでも主にsetCookie()関数を中心に説明する。
Cookieに関して注意する必要があるのは、Cookieを設定するのはサーバだが、送信するのはクライアントであるということ。
クライアント(ブラウザ)によって、サポートの有無は異なり、細かい部分での動作に相違がある可能性がある。

関数名解説
setCookie()Cookieを設定・削除する。(その際暗黙にURLエンコードする)
setRawCookie()URLエンコードせずに、Cookieを設定・削除する。
header()ヘッダを送信する。


setCookie()関数は、Cookieの設定と削除を行う基本的な関数である。
日本語のような、8ビット文字や、バイナリデータをCookieデータとして設定すると、暗黙のうちにURLエンコードしてくれる。
そのため、ほとんどのケースでは、setCookie()関数だけでCookieが使える。
この関数には、次のようにいくつもの、オプションがあるので、使い方はパラメータの与え方によって、いくつかのバリエーションが生じる。


boolsetCookie(<Cookie名>,<Cookie値>
,<有効期限>,<パス>,<ドメイン>,<セキュアフラグ>,<HTTPフラグ>)
<Cookie名>に<Cookie値>を設定し、その値の<有効期限>とする。
この場合はクライアントによって、<ドメイン>の<パス>以下のURIへのリクエストのみ送信され、
<セキュアフラグ>と<HTTPフラグ>のフラグに基づいて送信されるように指定する。


<Cookie名>はCookieの名前。変数名に相当するパラメータである。
これは必須の引数である。
<Cookie値>はCookieの値である。<Cookie名>で指定した変数に設定する値と考えることできる。
これ以降の引数は省略可能だが、<Cookie値>を省略したときに、Cookie値が削除されるわけではない。(クライアントに依存する)。
<有効期限>はCookieの有効期限を1970年1月1日からの秒数で指定する。
PHPのtime()関数を用いると、1970年1月1日からのからの秒数を得ることができる。
<パス>はそのCookieを関連付けるwebサイトとしてのURIである。
これを設定した場合、クライアントは該当パスへのリクエストにのみCookieを送信する。
<ドメイン>は、そのCookieを関連付けるwebサイトのドメインを指す。
デフォルトはFALSEなので、HTTPでもHTTPSでも設定される。
<HTTPフラグgt;は、HTTP(S)の場合のみCookieを設定する場合にTRUEとする。
これはたとえば、JavaScriptからのアクセスには、Cookieを設定しないことを意味する(ただしクライアントがサポートすること)。
この関数は、HTTPヘッダを送信することになる。
そのため、HTTPボディを送信する前に呼びださなければならない。
通常はスクリプトの先頭部(冒頭に改行やコメントを書いてもいけない)にPHPブロックを記述して、その中で呼び出す。
以降では、この関数を使ってCookieをつかって、Cookieを操作する方法を説明していく。
なお、setRawCookie()関数は、setCookie()関数よりHTTPに近い形で扱えるようにしたものである。
日本語のような8ビット文字やバイナリデータをURLエンコードせずに送信する。
引数はsetCookie()関数と同じである。
またヘッダを送信するheader()関数をも利用できるが、header()関数を使用する場合は、Cookieの構造と動作を正確に把握しておく必要がある。

■Cookieの設定


Cookieの設定は次のように行う。
次の例は3通りの方法で設定しているが、いずれも「SampleCookie」という名前で$userKey変数のCookieを設定している。

<?php
$userkey = "inakazu";

//該当サイトに有効期限60秒のCookieを設定
setcookie("SampleCookie",$userkey,time() + 60);
//該当サイトのpart4app/cookies/以下にCookieを設定する
setcookie("SampleCookie",$userkey,time() + 60,
            "/part4app/cookies");
//サイトwww.example.co,jpにCookieを設定
setcookie("SampleCookie",$userkey,time() + 60,
            "/part4app/cookies/","www.example.co.jp");
?>

<html>
<head><title>Cookieのセット</title></head>
<body>
<p>クッキーが保存されたか確認せよ
</p>
</body>
</html>

実行結果は以下の通り
ina02_20110811180407.jpg

クッキーが保存されているかどうかの確認
ina03_20110811184429.jpg

いずれの例も有効期限はtime()関数を利用して、「現在60秒後」設定している。
絶対的な日時を設定する場合は、秒数を計算する必要がある。
2番目の例ではパスを設定しているが、パスを設定すると、そのパス以下にあるURIには全てCookieが送信されるようになる。
3番目の例はさらにドメインまで指定した例だが、架空のドメインなので実行例では保存されない。


■配列のCookie

配列のCookieを設定することも可能。設定方法はCookie名を配列の形式で記述するだけ。

<?php
$userkey = "inakazu";

//該当サイトに有効期限60秒のCookieを設定
setcookie("SampleCookie",$userkey,time() + 60);
//該当サイトのpart4app/cookies/以下にCookieを設定する
setcookie("SampleCookie",$userkey,time() + 60,
            "/part4app/cookies");
//サイトwww.example.co,jpにCookieを設定
setcookie("SampleCookie",$userkey,time() + 60,
            "/part4app/cookies/","www.example.co.jp");
?>

<html>
<head><title>Cookieのセット</title></head>
<body>
<p>クッキーが保存されたか確認せよ
</p>
</body>
</html>

出力結果は、以下の通り
ina04_20110811184534.jpg

クッキーが保存されているかどうかの確認
ina05_20110811184555.jpg

実行結果をみると、配列になっている。


■Cookieの参照

Cookie設定したら、そのCookie値をチェックするページも必要である。
Cookieを参照できる関数もあるが、一般にCookieを参照するには、定義済み変数を使う。
PHPエンジンはリクエストを受け取ったときに、リクエストと共に送信されたCookieは配列変数$_COOKIEに格納される。
変数$_COOKIEは、クッキーの名前をキーとして持つ配列なので、print_r関数で全ての表示することも可能。


<?php
echo $_COOKIE['SampleCookie'];
?>




■Cookieの削除


削除は、基本的に空文字列("")を設定すればいいのだが、それだけでは以前のバージョンのブラウザでうまく削除できないことがあった。
そのため、確実に削除するために有効期限も確実に過去の日時(1日程度)を指定する。
具体的には、前述のコードなら次のようにして削除する。


<?php
#一日前を取得する
$expire = time() - 3600;
setCookie("SampleCookie",'',$expire);
echo '削除完了';
?>




空文字列を設定して、なおかつ過去の日時を有効期間として設定するという2点に注意。
配列を削除するときは、各要素を削除する。


<?php
$expire = time()-3600;
setcookie("CookieArr[0]",'',$expire);
setcookie("CookieArr[1]",'',$expire);
?>




■セキュリティ上の注意


Cookieはセキュリティホールになりやすいため、考えられる対策は全て対策するようにするべし。
Cookie名(name)は、アプリケーション内の役割を直接表現しないようにする。
たとえば、「password」などはさけるべしというか、もってのほか。
そもそもパスワードを送信してはいけない。
値(value)は極力アプリケーション内での振舞いに直結しないデータを設定する。
この値データでDBから検索するなどワンクッション入れるようにして、矛盾のあるデータならDBから検索できないように値にしておく。
もちろん検索エラー時の表示も対策しておく。
できるだけ、pathを設定してwebアプリケーションのうち、無関係なパスへのリクエストにはCookieを送信しないようにする。
ルートにCookieを設定してしまうとどこにセキュリティホールがあるか把握が困難になる。

【PHP】PHP復習二十八日目

【PHP】PHP復習二十八日目

ファイルのアップロード/ダウンロードその2


■ファイルのダウンロード

webアプリケーションにおいて、ファイルのダウンロードとは、特別なものではない。
つまり、通常の動作がHTMLのダウンロードになっているためである。
ただし、PHPの場合は原則的にHTMLのダウンロードがデフォルトの振る舞いになっているため、それ以外のファイルをダウンロードさせるときには、いくつかの配慮が必要になる。

■HTTPヘッダとファイルのダウンロード


ところでブラウザを使っていると、ダウンロードするファイルの種類によって、ブラウザの画面中に表示(たとえば、画像ファイル)されたり、ダウンロードダイアログボックスが表示された上で、ファイルに保存する(例えばZIPファイル)ケースがある。
これらの違いは何か?
一見、ダウンロードするファイルの拡張子で判断しているようにも思えるが、実は無関係。
HTTPヘッダを用いて判断している
なので、PHPからHTTPヘッダに変更を加えることによって、HTML以外のデータを送信しているようにブラウザに認識させることができる。

voidheader(<HTTPヘッダ文字列>)
HTTPヘッダとして、<HTTPヘッダ文字列>を送信する。
HTTPヘッダ以外は何も送信していない状態で呼びだす必要がある。


<HTTPヘッダ文字列>は「HTTPヘッダ名:HTTPヘッダ値」の形式で指定する。
次の例は、「image.jpg」というファイル名の画像ファイルをダウンロードする場合の処理である。

header("Content-Type":image/jpeg)
header("Content-length":.fileSize('image.jpg'));
readFile('image.jpg');


多くのユーザーは画像をブラウザ中に表示するように設定しているので、これはファイルの「ダウンロード」ではなく「表示」として振舞う。
この例で重要なのは、header()関数で送信しているContent-Typeという名のHTTPヘッダである。値として、「image/jpeg」を送信している。
Content-Typeヘッダはメディアタイプを指定する。
HTMLの場合は、text/html、JPEG画像の場合はimage/jpegなどとなる。
ブラウザはこのメディアタイプをみて、表示可能と判断したもののみ表示する。逆に表示可能でないものは全てダウンロードダイアログボックスが表示される。
ダウンロードさせたい場合は、「application/octet-stream」を利用する。
また送信するデータのサイズを、「Content-Length」ヘッダに指定したほうがいい。
上記の例では、画像ファイルなので、fileSize()関数を使用しているが、変数に格納されているデータならstrLen()関数を使う。
またHTTPヘッダはデータの本体よりも、先に送信されなければならない。
よって、「header()関数の呼び出しはスクリプトの先頭部」にかかなければならない。

■ダウンロードファイルのファイル名

ファイルを保存するときに、多くのブラウザはデフォルトで保存ファイル名を認識する。
このファイルはどのようにして決められるのか?
このファイル名のHTTPヘッダに入れておくべきなのか?
実は、これもブラウザの振る舞いの一部なので、ブラウザの実装に依存する。
そのため、スクリプト側から制御は難しいが、このエントリでは可能な限り制御するという方針で説明する。
まず、ブラウザを見た時、ダウンロードするべきファイル名はスクリプトのファイル名になることに注意。
HTTPの規約の中には、ダウンロードするファイル名を指定するためのHTTPヘッダは存在しないためである。
ダウンロードする仕組みを「fileDownload.php」というファイル名のスクリプトにすると、ダウンロードする際のファイル名も、「fileDownload.php」を候補とする。
そのため、古いブラウザではこのファイル名でしかダウンロードできず、ダウンロード後にリネームが必要なことがあった。
しかし、それでは不便なため、なんとかしてサーバからダウンロードファイル名を指定する方法(サーバから指定してもらう方法)を模索するブラウザが登場した。
その結果、メールの添付ファイル名を指定するときと同じHTTPヘッダをつけて指定可能とするブラウザが登場した。
具体的には、「Content-Discription」ヘッダをつけて、そのfilename属性でファイル名を指定するというものである。
これは、HTTPには規定のないヘッダなので、HTTPの使用を逸脱した使い方である。
Content-Discriptionヘッダにしてみても、このヘッダはメールにつけるものなので、HTTPのヘッダにつけるのは想定外の使い方である。
しかし、これも広く使われるようになった。

以下に例を示す。


<?php
if (FALS !== strpos($_SERVER['HTTP_USER_AGENT'], "Gecko")) {
#Firefoxの場合
$downName = mb_encode_mimeheader('ダウンロード.txt',"SJIS","B");
}
else{
//IEの場合
$downName = urldecode(
mb_convert_encoding('ダウンロード.txt', 'UTF-8','SJIS'));
}

header("Content-Type:application/octet-stream");
header('Content-Disposition:attachment;filename='.$downName.'"');
header("Content-Length:".filesize(inaternalFile));
readfile('internalFile');
?>




実行結果を以下に示す

ina03_20110810215227.jpg


■定義済み変数「$_SERVER」について
定義済み変数$_SERVERは、PHPエンジンが自動生成する配列変数である。
HTTPヘッダやサーバの環境変数、スクリプトの位置やクライアントのIPアドレスなど色々な情報を持っている。
$_SERVERはサーバが生成する情報にアクセスするので、どんな値にアクセスできるかはサーバに依存する。
つまり、それぞれの環境によって使えるキーと使えないキーが存在する。以下に主なキーとその内容についてまとめる。

キー内容
HTTP_HOST
HTTP_USER_AGENT
HTTP_ACCEPT
HTTP_ACCEPT_LANGUAGE
HTTP_ACCEPT_CHARSET
現在のHTTPリクエストの各ヘッダの値
HTTP_REFERER現在のページへのリンク元
PATH
SystemRoot
COMSPEC
WINDIR
各環境変数の値
SERVER_SOFTWAREレスポンスヘッダ上に書かれているサーバの認識文字列
SERVER_NAME現在のスクリプトが実行されているサーバのホスト名
SERVER_ADDRwebサーバのIPアドレス


キー内容
SERVER_PORTwebサーバの通信ポートとして使用されているポート番号
REMOTE_ADDR現在ページを見ているIPアドレス
DOCUMENT_ROOTドキュメントルートのフルパス名
SERVER_ADMINhttpd.confに記述されているSERVER_ADMINディレクティブの値
REQUEST_METHODページにアクセスする際に使用されたHTTPのリクエストメソッド
QUERY_STRINGページがアクセスされた際に付加されたクエリストリング
REQUEST_URIページにアクセスするために指定されたURI
PHP_SELF現在実行しているスクリプトのドキュメントルートからのパス
argcコマンドライン実行時に、スクリプトに渡された引数の配列
argvコマンドライン実行時に、スクリプトに渡された引数の数



【PHP】PHP復習二十七日目

ファイルのアップロード/ダウンロードその1

■ファイルのアップロード


以下では、ファイルのアップロードについて解説していくが、まずphp.iniの以下の設定について確認しておくべし。

【php.iniの530行目付近】
file_uploads = On
upload_tmp_dir =
upload_max_filesize = 2M


file_uploadsはファイルのアップロードを処理するかどうか指定する。
アップロードされたファイルは、PHPエンジンによってスクリプトが起動される前に処理される。
その事前処理の有無を選択する。
デフォルトで「On」になっているはず。
upload_tmp_dirは、スクリプトに渡される前にファイルとして受信するための、一時ディレクトリを指定するものである。
これはデフォルト(Windowsの一時ディレクトリ)のままでもいい。
upload_max_filesizeは、アップロードを許す最大ファイルサイズを指定する。
この指定は、webアプリケーションの運用が始まってからの特定の(大きな)ファイルがアップロードできない障害となって問題となることが多いので、注意するべし。

■ファイルアップロードの基礎

一般的にファイルを送信するフォームは次のようになる。


<HTML>
<
HEAD><TITLE>ファイルアップロードの例</TITLE></HEAD>
<
BODY>

<
H3>multipart/form-data(upload単独)</H3>
<
FORM enctype="multipart/form-data" action="uploadTo.php" method="POST">
Send this file: <INPUT type="file" name="userfile" /><BR>
<
INPUT type="submit" value="Send File" /><BR>
<
/FORM>

<
/BODY>
<
/HTML>




出力結果は以下の通り
ina01_20110810153121.jpg

ファイルをアップロードする側はPHPスクリプトでなければならない必要はないので、ここではHTMLファイルとしている。
このフォームで重要な点は、まず
タグのenctype属性として、「multipart/form-data」を指定するという点である。これによって、任意のデータが送信できるようになる。
またファイルを送信するためのフォーム要素として、type属性を「file」と指定した<input>タグが必要である。
この要素がファイル一つに相当する。
ブラウザ画面上ではファイル名を指定するテキストフィールドと、ファイル選択ダイアログボックスを表示するボタンがセットで表示される。
送信側となるHTMLにはこの2点が必須だが、<input>タグが持つname属性の値は受信側のスクリプトにも関係している。この例のHTMLでは、ファイルに対応する<input>タグはname属性として「userfile」と記述した。
一方の受信側は、多くの場合ファイルの移動やDBのへの記録などを行うスクリプトでなければならない。
ただし、このときスクリプトでは送信フォームと対応した記述が必要になるので、その理由から送信元のフォームと受信スクリプトを同じファイルにするケースが多い。
ここでは、別のファイルとして用意して<FORM>タグのaction属性にそのファイル名を指定しているが、同じファイルにする場合は、その処理の最初にファイル送信の有無を判断する必要がある。
先ほどのフォームから送信されたファイルを処理する例が以下のコードになる。


<?
if(FALSE !== $_FILES['userfile']['error']){
if(0 != $_FILES['userfile']['size']){
if(FALSE !== strpos($_FILES['userfile']['type'],'image/')){

$base = baseName($_FILES['userfile']['name']);
echo "<ima src '= ".$base."'>";
}
}
}

?>




このスクリプトでは、まず定義済み変数$_FILESを使っている。
フォームにファイル送信<INPUT>タグがある場合、この変数$_FILESに情報が集約して格納されている。
この配列変数はグローバル変数なので、常に存在する。
したがって、ファイルアップロードを行う場合はまずこの変数を使うと覚えておく。
この配列には、<INPUT>タグのname属性の値のキーとして情報が格納される。
この例では「userfile」としたので、$_FILES['userfiles']とすれば、アップロードされたファイルについて情報が得られます。
この$_FILES['userfile']の値は、さらに以下のような配列になっている。

キー意味
errorアップロードの状態(0なら成功)0
sizeアップロードされたファイルのサイズ(バイト単位)。
空(サイズが0)のファイルをアップロードした場合は、
キーがerrorが0になり成功とみなされてしまうので注意。
2007992
nameアップロードする前のファイル名IMG_0432.JPG
typeアップロードされたときにクライアントによって指定
されたメディアタイプ。適切にファイルの中身を示す
かどうかはクライアントの設定次第。
image/pjpeg
tmp_name受信したファイルの一時ファイル名C:\Windows\PHP5.tmp


キーnameは、ファイルをアップロードすうユーザがブラウザで選択した時点でのファイル名が入っている。
これを用いて受信したファイルにも同名にリネームしたい場合には注意が必要である。
それは元のファイル名とディレクトリ名に日本語が含まれている場合、それがただしく解釈されずに文字化けを起こす可能性があるということ。
PHPを動作させるプラットフォームやクライアントのプラットフォーム、クライアントの種類やバージョンに大きく影響を受けるので、この名前を使うときは、十分にテストする必要がある。
キーtmp_nameは、一時ファイル名である。
アップロードされたファイルは、PHPエンジンにより一時ファイルに保存される。
そのため、スクリプトでは既にファイルになった状態で受け取る。
この一時ファイルはスクリプトが終了するときに、自動的に削除されるので、必要なファイルであれば、スクリプトでコピーするか移動するかの処理を行う。

■複数のファイルをアップロード

複数のファイルをアップロードするときも同様に処理するが、フォームの配列要素を使うと、便利になる。
このときは、フォームにも固有の記述が必要となる。


<HTML>
<
HEAD><TITLE>複数ファイルのアップロード</TITLE></HEAD>
<
BODY>

<
H3>multipart/form-data(upload複数)</H3>
<
FORM enctype="multipart/form-data" action="uploadMTo.php" method="POST">
Send this file1: <INPUT type="file" name="userfile[]" /><BR>
Send this file2: <INPUT type="file" name="userfile[]" /><BR>
Send this file3: <INPUT type="file" name="userfile[]" /><BR>
Send this file4: <INPUT type="file" name="userfile[]" /><BR>
<
INPUT type="submit" value="Send File" /><BR>
<
/FORM>

<
/BODY>
<
/HTML>




出力結果は以下の通り
ina02_20110810153239.jpg

上記のコードでは、ファイルアップロードのための<INPUT>タグが複数あるが、そのname属性の書き方がPHPの配列形式になっている。
このように記述することにより、PHPエンジンが配列として、処理するようになる。
以下が、上記のコードから呼びだすスクリプトである。


<?
foreach(array_keys($_FILES['userfile'][error]) as $fileEntry)
{
if(FALSE !== $_FILES['userfile']['error'][$fileEntry] &&
0 != $_FILES['userfile']['size'][$fileEntry])
{
if(FALSE !== strPos($FILES['userfile']['type'][$fileEntry],'image/'))
{
base = baseName(
$_FILES['userfile']['name'][$fileEntry]);
copy($_FILES['userfile']['tmp_name'][$fileEntry],$base);
echo "<IMG src = '" . $base . "'>";
}
}
}
?>




このコードは、前述のコードを同じ処理を各ファイルに対して行うものである。
各ファイルに同じ処理をループするなら、まずループ条件としてファイルを示すキーの一覧を取得する必要がある。
ここでは、array_keys()関数を用いて以下のようにしている。

array_keys($_FILES['userfile']['error'])

array_keys()関数は、配列のキーを配列として返す関数である。キーは「error」である必要はないが、sizeなり、nameなり、いずれかのキーを使う。array_keys()関数が返す配列からforeachループに入る。

プロフィール

稲員勇輝

Author:稲員勇輝
特に自分を象徴する物がありません。
特徴がないのが特徴です。

FC2カウンター
カレンダー
02 | 2024/03 | 04
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 - - - - - -
タグそして検索
カテゴリ
最新記事
月別アーカイブ
最新トラックバック
最新コメント
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード