Day6

ファイル転送システム

Topへ

Day5へ

はじめに

大容量転送ファイルのシステムは無料で多く存在しているにもかかわらず、あえて作ろうと思うアホなおいさんです。
さらに虚しいのは、利用する人もいない状況の中、システム作成に挑戦することです。
唯一の利点は、保存期間に制限がないことぐらいです。

Step1

ログイン画面の作成

image

今回は、共通のIDとパスワードではなく、ユーザー毎にIDとパスワードを登録してもらいそのアカウントでログイン してもらう形にしようと思います。
ということで、「Visual Studio Code」のファイルメニューから「新しいテキストファイル」を選択します。

image

まずは、データベースに接続する際の、データベース名、ユーザー名、パスワード等を定義する用のファイルを作成します。
これをしておけば、実際に運用するデータベースに移行する際にこのページだけ変更すれば良いことになります。
なので、他のファイルからわざと切り離します。
ということで、「名前を付けて保存」をします。ファイル名は「env.php」とします。
あとおいさんの都合で「lf_transfer」というファルダを作成してその中に保存します。

image

このファイルでのコードは簡素で、画像のとおりになります。
ここでは、「define」という定数を定義する命令文を用いてデータベース名等を定義します。
この命令文の良いところはプログラムのどこからでも呼び出せるグローバルな定義ができることです。
以上で、このファイルでの作業は完了になります。

データベース側にさきほど設定したデータベース名やユーザーを登録します。
ただし、いきなり運用するサーバーで設定するのは憚れるので、「MAMP」の仮想サーバーに設定します。
「MAMP」のことがわからない方は「Day2」を参照ください。
ということで、「MAMP」を起動します。

image

「Open WebStart page」を押します。

image
image

「TOOLS」の「PHPMYADMIN」を選択します。

image

「New」を選択します。

image

今回データベース名は「flft」とします。入力後、「Creat」ボタンを押し確定します。

image

テーブル名を決めます。今回は「usertb」とします。またColumn数は3とします。
これは、id、id名及びパスワードの3項目をデータベースに保存したいためです。

image

画像のとおり入力し、「Save」ボタンを押します。

image

もう一度「New」ボタンを押します。

image

「Check privileges」を押します。

image

「Add user account」を押します。

image

画像のように入力して、「Go」ボタンを押します。これでデータベース側の作業は完了になります。

image

次は実際にデータベースに接続する機能を備えたファイルを作成します。 「新しいテキストファイル」を選択します。

image

名前を「dbconnect.php」として保存します。

image

「require_once」でファイル「env.php」を呼び出します。
またエラー表示してもらえるように「display_errors」を「true」にしておきます。 データベースとの接続用のメソッドは「connect」とし、この中に接続するコードを書いていきます。

image

データベースに接続するためのSQL文を設定し、変数「$dsn」に格納します。
ここでポートの設定(8889)をしていますが、通常はいらないみたいです。おいさんの場合はこれを設定しないと エラーがでてしまうのでやむなく設定しております。

image

画像は実際にデータベースに接続するコードになります。
中身は今一つわかりません。こういう書き方だという理解でお願いします。
これで、データベースに接続するファイルの作業はすべて完了になります。

image

データベースに接続する準備ができたので、次はデータベースに何のデータを入れるかを命令するファイルを作成します。
「新しいテキストファイル」を選択します。

image

名前を「userlogic.php」として保存します。

image

「dbconnect.php」を一度読み込みます。
次に「UserLogic」という名前のクラスを設定します。ちなみにクラスなので名前はなんでも良いのです。

image

まずは、ログインしているかの確認するメソッドを作成します。
メソッド名は「checkLogin」とします。また、メソッドを定義する場合、その情報を書き込んだほうが良いらしく、 メソッドの上に表示するようです。今回は、引数がなくログインしているかしていないかで、「true」か「false」を 返す関数になります。 なので、画像のような書き方になります。ちなみに「@param」に引数の情報(変数の型と変数名)を書き、「@return」に 返り値(変数の型と変数名)を書くようです。

image

メソッド内にコードを追記します。ここでは、連想配列「$_SESSION」の中の「login_user」キーに値がなければ 「false」を返すコードになります。
ここで、いきなり「$_SESSION」という変数(配列)が登場していますが、まずはこれが何かについて説明します。
そもそもPHPでのWebアプリケーションには、それ自体に保存機能を有していなかったようです。そのため今回のように ログインしたかどうかの情報を保持することができなかったようです。そこで、一次的な情報を格納できるよう「$_SESSION」という スーパーグローバル変数ができたようです。
今回はこの変数に「login_user」キーが設定されているかを利用しているコードになります。 ここで一旦このファイルの作業は完了とします。

image

ここからやっとログイン画面を作成していきます。
「新しいテキストファイル」を選択します。

image

ファイル名は「login_form.php」とします。

image

「!」→「Tab」キーを押してhtmlのベースコードを表示させます。
また、タイトルを「ログイン画面」とします。

image

css文を追記して、スタイルを指定します。

image

css文の続きになります。これでcss文は完了になります。

image

「body」タグ内にログイン画面を作成していきます。
「form」タグでユーザーIDとパスワードを入力できるようにします。

image

ブラウザを起動して実行した画面になります。シンプルですがログイン画面になっています。
この時点でIDとパスワードを持っていない場合は、一番下の「新規登録はこちら」ボタンを押していただくことなります。

image

ファイル上部にphp文を差し込みます。
まずは、「session_start();」というコードを追記します。
これは、以前触れた「$_SESSION」をこのファイルで有効にするコードになります。
最後に、「userlogic.php」を一度読み込みます。

image

ブラウザを起動して実行した画面になります。シンプルですがログイン画面になっています。
この時点でIDとパスワードを持っていない場合は、一番下の「新規登録はこちら」ボタンを押していただくことなります。

image

ファイル上部にphp文を差し込みます。
まずは、「session_start();」というコードを追記します。
これは、以前触れた「$_SESSION」をこのファイルで有効にするコードになります。
最後に、「userlogic.php」を一度読み込みます。

image

通常別クラスのメソッドを使用する場合、インスタンスをして使用できるようにしますが、画像のようなコードでもメソッドを 使用でるようです。
今回は、「checkLogin」メソッドを使用しログイン確認ができていれば、「mypage.php」ファイルへ遷移するようなコードになります。

image

「mypage.php」ファイルへ遷移せず、下の行へプログラムが流れてきた場合は何かしらのエラーを抱えていることになります。
なのでるので、変数「$err」にその内容を格納しておきます。
格納が終われば一度セッションを止めるようにしています。

image

エラー内容は知りたいので表示できるようにしておきます。
これで、このファイルでの作業はすべて完了になります。

image

このファイルでの遷移先は「signup_form.php」、「login.php」及び「mypage.php」の3ファイルになります。
どれから作成してもよいのですが、まずは新規登録機能から実装使用と思います。
「新しいテキストファイル」を選択します。

image

名前を「signup_form.php」として保存します。

image

「!」→「Tab」キーを押してhtmlのベースコードを表示させます。
また、タイトルを「ユーザー登録画面」とします。

image

css文でスタイルの設定をします。

image

続きになります。

image

「body」タグ内にコードを追加していきます。
ここでは新規登録になりますので、IDとパスワードを入力できる画面構成にします。
入力したデータは「POST」形式で「register.php」ファイルに送るようにします。

image

ブラウザで画面を確認してみます。まあシンプルですが機能としては十分と思います。

image

ログイン済みかの確認のため、PHP文を差し込みます。
コードは画像のとおりになります。

image

追加したコードの1行目は、三項演算子という書き方になります。内容としては、「$_SESSION['login_err']」に値が存在すれば その値を、値が存在しなければNullを返すコードにしています。
今回はその返り値を変数「$login_err」に格納し、その後「$_SESSION['login_err']」の値を消すようにしています。

image

ここからは、セキュリティ上の対策を2つしようと思います。
そのコードは別ファイルで関数化することにしますので、「新しいテキストファイル」を選択します。

image

名前を「function.php」として保存します。

image

一つ目のセキュリティ対策は、クロスサイトスクリプティング(xss)攻撃の対策になります。どんな攻撃かよく理解できませんが、 とりあえずエスケープ処理というものを実行すれば良いようです。
コードとしては簡単で画像のとおり、対象の文字に「htmlspecialchars」をかぶせれば良いようです。

image

二つ目のセキュリティ対策は、クロスサイトリクエストフォージェリ(CSRF)攻撃の対策になります。
こちらは、正規ユーザーを装ってサーバに偽のリクエストを送信し、意図しない行動を取らせる攻撃ということのようです。
この攻撃を防ぐためにワンタイムトークンなるものを採用するようです。
これは、まずページを表示する前にランダムな文字(トークン)を生成し、ユーザーセッションに保存します。今回はこれを 「functions.php」で行います。その後、今回の場合「signup_form.php」で生成したトークンを「hidden」形式で送ります。
リクエスト先(register.php)でその送信されたトークンとセッションに保存されたトークンと一致すれば処理を続けるという 仕組みのようです。 兎にも角にも、この画像ではトークンの生成とそれをセッションに保存する処理を関数化しています。

image

「signup_form.php」ファイルにも戻ります。そのファイル内で「functions.php」の関数を使用したいので、 一度読み込みます。

image

画像のとおりのコードを追加し「hidden」形式で他のデータとともに、「register.php」に送ります。

image

受け取り先の「register.php」ファイルを作成します。
このファイルでは、IDとパスワードを保存する処理を行います。
「新しいテキストファイル」を選択します。

image

何度も出ていますが名前を「register.php」として保存します。

image

コードを入力する前に一度「userlogic.php」に移動し、新規保存のメソッドを作成します。 「userlogic.php」に移動し、「createUser」メソッドを準備します。

image

画像はメソッド内のコードになります。今回は新規に保存なのでSQL文は「INSERT INTO」になります。
また安全対策としてパスワードをハッシュ化しています。これは、アルゴリズムより、適当な文字に置き換えて元のデータを 自分や他の人が推測できなくするようです。
なのでデータベースのパスワードの項目はよくわからない文字が羅列している値が保存されている状態になります。
これで、「userlogic.php」ファイルでの作業は終了になります。

image

「register.php」ファイルに戻ります。
まずはトークンが一致するか確認します。コードは画像のとおりになります。

image

次は入力されたデータの確認(バリデーション)を行います。
送られてきたデータは、「filter_input」で受け取るようにします。

image

バリデーションでエラーが無ければ、先ほど作った新規保存メソッドを利用してデータベースに保存します。

image

html分部を作成していきます。
「!」→「Tab」キーを押してhtmlのベースコードを表示させます。

image

css文によりスタイルを設定します。

image

続きになります。

image

エラーがあれば表示するようにします。
もしなければ「ユーザー登録が完了しました」を表示するようにします。
これで、このファイル他、「signup_form.php」からの一連の作業が完了になります。

image

まだ何もしていない残りのファイルは、「login.php」及び「mypage.php」になります。
ここからは、先に「login.php」から作成していきます。
「新しいテキストファイル」を選択します。

image

名前を「login.php」として保存します。

image

このファイルでは、「login_form.php」から送られてきたidとパスワードがデータベースに登録されているか 確認するものになります。
まずは、送られてきたデータのバリデーションを行います。コードは画像のとおりになります。

image

エラーがあった場合表示するようにします。

image

まだ、UserLogicクラスにloginメソッドを作成していないですが、あるものとして実行処理をします。
これにより、アカウントをもっているユーザーかどうか確認できるようになります。

image

html分部を作成していきます。「!」→「Tab」キーを押してhtmlのベースコードを表示させます。

image

css文でスタイルの設定をします。

image

続きになります。

image

画像は「body」タグ部分になります。これでこのファイルの作業は完了になりますが、「userlogic.php」ファイルにメソッドを 作成することを残しているのでそちらをしていきます。

image

「userlogic.php」ファイルに移動し、loginメソッドを作成します。
引数は、ID名とパスワードになります。

image

次にID名から関連するデータを取得する処理をしますが、これは別メソッドで実行するようにします。

image

etUserByIdnameメソッドを作成します。単純にID名からデータを取得するコードになります。

image

要求したデータを取得できましたので、パスワードの照合を行います。
ここで、「password_verify」はユーザーが入力したパスワードと、データベースに保存されているハッシュ化された パスワードを比較し、一致するかを確認するために使用される命令文のようです。
一致した場合、「session_regenerate_id(true)」で古いセッションIDを無効化させるようです。ここは理解できていません。
ともかく画像のとおりのコードで作業は完了になります。

Step2

マイページの作成1

image

最後に残しておいた「mypage.php」ファイルを作成します。このページはすでにログインできているページになりますので、 ここからが本来達成したい機能(ファイル転送システム)を実装する作業になります。
「新しいテキストファイル」を選択します。

image

名前を「mypage.php」として保存します。

image

ログインの確認をしておきます。ログインできていれば、変数「$login_user」にID名を格納します。

image

「!」→「Tab」キーを押してhtmlのベースコードを表示させます。

image

phpファイルの保存先に、新たに「uploads」ファルダを作成します。
このフォルダの中に転送したいファイルを保存するようにします。

image

先ほど作ったファルダの下層にログイン名ごとにファルダを確保しようと思います。
また、その上の行の変数名を変更します。(意味はないです。名前が気に食わないだけです)

image

はじめはログイン名のフォルダが存在しないので、「mkdir」でフォルダを作成します。

image

ブラウザで実行し、フォルダが作成されているか確認してみます。
画像がその結果です。無事ログイン名のフォルダが作成されています。

image

メインページの画面を作成していきます。
何はなくともファイルをアップロードできる機能が必要になりますので、まずはそのコードを追加します。
追加する場所は「body」タグ内になります。

image

ブラウザで起動して確認してみます。画像がその結果になります。
今回は、cssを後回しにして先に機能の実装を優先することにします。

image

ファイルのアップロードの入力画面は作成しましたので、そのデータを受け取り保存するコードを追記します。
コードは画像のとおりになります。

image

画面に保存されたファイルを表示するため、保存されたフォルダ・ファイル群を取得します。
取得方法は、「scandir」関数で可能になります。取得したフォルダ・ファイル群(配列)は変数「$files」に格納します。

image

保存されているフォルダ・ファイル群を表示させます。「ul」タグで表形式とし、各行にファイル名とダウンロード及び削除を実行 するファイルへのリンクを「a」タグで遷移するようにしています。また、リンク先のパスの後に「?」を付け、キーと値(file=ファイル名) を送るようにしています。これで受け取る側でファイル名を取得できるようにしておきます。

Step3

削除ファイルの作成1

image

アップロードされたファイルを削除する機能を実装します。
「新しいテキストファイル」を選択します。

image

名前を「delete.php」にして保存します。

image

最初の部分は「mypage.php」ファイルと同様になります。

image

削除の情報は「mypage.php」ファイルから「file=ファイル名」で送られてきますのでそれを「$_GET」で受け取ります。
今回は、合体演算子(??)を使用しています。これは、「$_GET['file']」がnullの場合、空文字('')を代入する命令文になります。

image

実際に削除を実行する処理をします。「unlink」でファイルは削除できるようです。
これで、「delete.php」の作業は完了になります。

Step4

ログアウトファイルの作成

image

ログアウト機能を実装します。
「新しいテキストファイル」を選択します。

image

名前を「logout.php」として保存します。

image

コードは画像のとおり簡素になります。これで、このファイルでの作業は完了になります。

Step5

CSSを追加する

image

css文でスタイルの設定をします。今は何も設定していないので画像のような画面の状態になります。

image

今回は、htmlファイルに直接css文を書き込まずに、別ファイルで作成することにします。
「新しいテキストファイル」を選択します。

image

名前を「style.css」として保存します。

image

css文のコードになります。内容は割愛します。

image

続きになります。

image

最後になります。これでcssファイルでの作業は完了になります。

Step6

マイページの作成2

image

「mypage.php」ファイルにcssを反映させます。まずは、cssファイルを指定します。
コードは画像のとおりになります。

image

適宜cssの設定をしていきます。

image

画像はcssを導入した画面になります。少し見栄えがよくなったような気がします。

Step7

フォルダ作成機能

image

ファイルマネージャー的な画面構成を目指しているので、やはりフォルダは作成できるようにしておきたい。
なので、その機能を実装しようと思います。「新しいテキストファイル」を選択します。

image

名前を「create_folder.php」として保存します。

image

これまでどおり、はじめは「mypage.php」のコードと同様になります。

image

フォルダを作成するコードになります。フォルダ名はPOST形成で送られてきた「folder_name」に格納されている値になります。
また、2行目の「trim」関数は先頭や末尾の空白等(空白文字、改行、タブ)を取り除く関数になります。
これで、受け側のファイルはすべて完了になりますので、次は入力側(mypage.php)にコードを追加していきます。

Step8

マイページの作成3

image

「mypage.php」ファイルに移動します。
フォルダ名を入力できる画面を作成します。コードは画像のとおりになります。

image

フォルダ名を表示できるようにします。
コードは画像のとおりになります。

image

ファイル表示の方ですが、このままのコードだとフォルダ名も表示されてしまいます。
なので、ファイルであれば表示するというコードに変更します。

image

画像は現段階までの画面になります。ここで「aaa」というフォルダをとりあえず作っていますが、 仮にこの「aaa」フォルダをクリックすると「folder="aaa"」という情報が再度このページ送られる コードになっています。これを利用して次に「aaa」フォルダに移動するコードを作成していきます。

image

送られた「folder="aaa"」から現在のディレクトリは「aaa」とわかるようにします。
まず、「folder="aaa"」のフォルダ名「aaa」をPOST形式で受け取ります。
その後、変数「$target_dir」に現在のディレクトリの場所を格納します。
最後にそのディレクトリ内のファイルのみを表示するようにパスを変更します。

image

再度ブラウザで画面を確認します。画面は「aaa」フォルダに移動したときの状況になります。
「aaa」のフォルダ内にはファイルをアップロードしていないので何も表示されないことがわかると思います。

image

フォルダ表示は完了しましたが、今のコードのままでは指定したフォルダ内にファイルをアップロードできません。
なのでコードを変更します。まず入力側のコードを変更します。変更内容は画像のとおりになります。

image

アップロードのコードに2行コードを追加します。これで指定したフォルダ内に保存ができるようになるはずです。

image

「delete.php」ファイルも変更する必要があります。まず送る側の情報量が足りないので追加します。
パスの情報を送りたいので「&path=パス名」を追加します。

Step9

削除ファイルの作成2

image

送られた情報を元に、「delete.php」のコードを変更します。
まずGETで「path」を受け取り、そのパス名で「unlink」を実行します。

Step10

マイページの作成4

image

「mypage.php」ファイルに戻ります。
現段階の機能では、ファイルを1つ1つアップロードする方法しかありません。
それは不便なので、まとめてアップロードできる機能を追加したいと思います。
まずは、入力側ですが必要ないですが「name」を変えてみました。

image

アップロードのコードを大幅に変更します。おいさんもここはコピペしてきた箇所なので中身が理解できていません。
それでもこれで複数のファイルをまとめてアップロードできるようになりました。

Step11

ダウンロードファイルの作成

image

やっとここまで来ました。ダウンロード機能を追加します。
「新しいテキストファイル」を選択します。

image

名前を「download.php」として保存します。

image

ファイルの先頭はいつもどおりログイン処理をします。

image

コードを追加します。ここもコピペの箇所で中身がよくわかっていません。でもダウンロードできました。
これで、このファイルでの作業はすべて完了になります。

Step12

マイページの作成5

image

ダウンロード機能を追加しましたが、1つ1つダウンロードするのでは大変なのでフォルダごとにダウンロードできるようにしていきます。
ということで「mypage.php」ファイルに戻ります。
入力箇所にコードを1行追加します。これで、まだ作っていない「download_folder.php」ファイルに遷移するようにします。

Step13

ZIP形成でダウンロードするファイルの作成

image

「download_folder.php」ファイルを作成します。
「新しいテキストファイル」を選択します。

image

当然、ファイル名は「download_folder.php」として保存します。

image

いつものログイン処理をします。

image

まずは、フォルダ名を取得し、そこまでのパスを変数「$folder_path」に格納します。

image

ここからはまったくわからないコードになります。それでも圧縮しダウンロードできました。
ただ、パスの数分フォルダが作成されており随分奥にファイルが格納されてしまっています。
コピペであるため解消しようにもできない状況です。なのでこのままになります。

image

ブラウザで一度確認してみます。現段階では画像の状態まで作りこみができています。

Step14

マイページの作成6

image

フォルダごとのダウンロード機能を追加しましたが、フォルダの削除機能を追加していません。
ということで「mypage.php」ファイルに戻り削除ができるようにします。
入力箇所にコードを1行追加します。これで、まだ作っていない「delete_folder.php」ファイルに遷移するようにします。

Step15

フォルダを削除するファイルの作成

image

「delete_folder.php」ファイルを作成します。
「新しいテキストファイル」を選択します。

image

名前を「delete_folder.php」とし保存します。

image

27行目までは、「download_folder.php」のコードと同様になるのでそのままコピペします。

image

フォルダ削除の場合、そのフォルダ内にファイルが残っている可能性があるのでその対策として先に関数を作成しておきます。
この中身は得意のコピペなので理解できていません。特に関数の中に関数を使用するという高等テクニックが使用されています。

image

関数を実行するコードになります。これでこのファイルでの作業は完了になります。

image

完成形を確認します。画像がブラウザを起動して表示される画面になります。機能としては少ないですが随分コードは長くなりました。
レンタルサーバへの移設は「Day5」と同様ですので割愛します。
また、フォルダを作成する際、権限の指定がいるようで、「0777」を追加する必要があるようです。ダウンロードにあるファイルは追加しています。