PHPでファイルをアップロードするシンプルな方法から、エラーチェックや容量制限を設定する方法も併せてご紹介します。
目次
ファイル構成
本記事は以下の2つのファイル構成を想定しています。
index.html
…フォームを設置したHTMLファイルupload.php
…フォームの遷移先でアップロード処理をするPHPファイル
シンプルなファイルアップロード
まずは、エラーチェックをしない必要最小限のファイルアップロードです。
サンプルコード
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <title>アップロード</title> </head> <body> <!--formのenctypeに"multipart/form-data"を設定する--> <form action="upload.php" method="post" enctype="multipart/form-data"> <!--input typeは"file"を設定する--> <input type="file" name="upload"> <input type="submit" value="アップロード"> </form> </body> </html> |
upload.php
1 2 3 4 5 6 7 8 9 10 |
<?php // ファイルの保存先 $uploadfile = '/var/www/files/memo.txt'; // アップロードされたファイルに、パスとファイル名を設定して保存 move_uploaded_file($_FILES['upload']['tmp_name'], $uploadfile); // 完了メッセージを表示 echo 'アップロード完了!'; |
これだけで実際にファイルのアップロードができます。
ファイルアップロードの流れ
ファイルアップロードは以下のような流れで動作します。
- ファイルアップロードフォームでアップロード
- サーバーの一時フォルダに一旦保管
move_uploaded_file()
で指定のパスに移動
ファイルアップロードフォームでUPされたファイルは、サーバーのテンポラリフォルダに一旦保管されます。
そしてmove_uploaded_file()
で指定したパスにファイルを移動させます。
ファイルアップロード用フォーム
HTMLでファイルアップロードを実現するには以下のポイントがあります。
form
タグのenctype
にmultipart/form-data
を設定
<form action=”upload.php” method=”post” enctype=”multipart/form-data”>input type
にはfile
を指定
<input type=”file” name=”upload”>
move_uploaded_file関数の構文
アップロードされたファイルを新しい場所に移動させます。
move_uploaded_file ( アップロードされたファイル名 , 移動先パス/ファイル名 )
グローバル変数「$_FILES」
上記サンプルコードにある$_FILES['upload']['tmp_name']
はアップロードされたファイルの情報が格納されたグローバル変数です。
以下のような構文になっています。
$_FILES [ アップロードフォームのinput name値 ] [ アップロードされたファイル情報の項目 ]
最初の[]
にはHTMLアップロードフォームのinput
属性のname
値が設定されます。
2番目の[]
にはアップロードされたファイル情報の項目が入ります。
ちなみに$_FILES
の中身は以下のような連想配列になっています。
Array(
[name] => memo.txt
[type] => text/plain
[tmp_name] => /var/tmp/php7UNOJY
[error] => 0
[size] => 45
)
配列で取得した各項目は以下のような内容になります。
項目 | 内容 |
---|---|
name | 元ファイル名 |
type | ファイルタイプ |
tmp_name | サーバーに一時保管されたファイル名 |
error | エラーコード |
size | ファイルのバイト数 |
上記項目を使って、エラーチェックなどを行います。
エラーコードは0
ならアップロード成功で、1
〜4
、6
〜8
は以下のようなエラーになります。
コード | エラー定数 | 説明 |
---|---|---|
0 | UPLOAD_ERR_OK | エラーなし |
1 | UPLOAD_ERR_INI_SIZE | php.iniのupload_max_filesizeのサイズを超えている |
2 | UPLOAD_ERR_FORM_SIZE | HTMLフォームで指定された MAX_FILE_SIZE を超えている |
3 | UPLOAD_ERR_PARTIAL | 一部のみしかアップロードされていない |
4 | UPLOAD_ERR_NO_FILE | アップロードされなかった |
6 | UPLOAD_ERR_NO_TMP_DIR | サーバー一時保管フォルダがない |
7 | UPLOAD_ERR_CANT_WRITE | ディスクへの書き込みに失敗 |
8 | UPLOAD_ERR_EXTENSION | PHPの拡張モジュールがアップロードを中止した |
さまざまなエラーチェック
エラーチェックはセキュリティやパフォーマンス的にも必須でしょう。
追求すればきりがありませんが、ここでは最低限のエラーチェックを追加したサンプルをご紹介します。
サンプルコード
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <title>アップロード</title> </head> <body> <!--formのenctypeに"multipart/form-data"を設定する--> <form action="upload.php" method="post" enctype="multipart/form-data"> <!--MAX_FILE_SIZE でファイルサイズを制限する--> <input type="hidden" name="MAX_FILE_SIZE" value="1000"> <!--input typeは"file"を設定する--> <input type="file" name="upload"> <input type="submit" value="アップロード"> </form> </body> </html> |
upload.php
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 32 33 34 35 |
<?php // ファイルの保存先 $uploadfile = '/var/www/files/memo.txt'; // ①POSTリクエストによるページ遷移かチェック if ($_SERVER['REQUEST_METHOD'] === 'POST') { // ②エラーコード2だった場合(HTMLのファイル制限超過) if ($_FILES['upload']['error'] === 2) { echo 'ファイルサイズを小さくしてください!'; // ③サイズが0だった場合(ファイルが空) } elseif ($_FILES['upload']['size'] === 0) { echo 'ファイルを選択してください!'; // ④テキストファイルじゃなかった場合 } elseif ($_FILES['upload']['type'] !== 'text/plain') { echo 'テキストファイルを選択してください!'; // アップロードが成功した場合 } elseif ($_FILES['upload']['error'] === 0) { // アップロードされたファイルに、パスとファイル名を設定して保存 move_uploaded_file($_FILES['upload']['tmp_name'], $uploadfile); // 完了メッセージを表示 echo '完了!'; // 上記以外の場合 } else { echo 'アップロードに失敗しました!'; } // POSTリクエストによる遷移じゃない場合 } else { echo '不正なアクセスです!'; } |
上記のように$_FILES
の値を使って、簡単ですがエラーチェックをしてみました。
丸囲み数字のエラーチェックを以下で解説します。
①POSTリクエストによるページ遷移かチェック
if ($_SERVER[‘REQUEST_METHOD’] === ‘POST’) {
サーバー変数でPOST
かどうかをチェックしています。
upload.php
に直接アクセスするのを防ぎます。
参考:サーバー変数一覧と実用例
②ファイル制限超過チェック
if ($_FILES[‘upload’][‘error’] === 2) {
HTMLフォームで指定されたMAX_FILE_SIZE
を超えた場合、エラーコード 2 が返されます。
ちなみに、以下のようなフォームの要素を1つ追加しています。
<input type=”hidden” name=”MAX_FILE_SIZE” value=”1000″>
隠し要素に以下の値を設定すると、HTML側でファイルサイズの制限をすることができます。
name
値にMAX_FILE_SIZE
を設定するvalue
値にファイルサイズの上限値をバイト数で指定する
注意:MAX_FILE_SIZE は input type=”file” 要素より前に設定しないと動作しません。
③ファイル存在チェック
} elseif ($_FILES[‘upload’][‘size’] === 0) {
$_FILES['upload']['size']
の値が0
だった場合、ファイルが空(アップロードするファイルが存在しない)と判定しています。
アップロードするファイルを選択しなさい!とメッセージを出します。
④ファイルタイプチェック
} elseif ($_FILES[‘upload’][‘type’] !== ‘text/plain’) {
ファイルタイプがテキストファイル以外をエラー判定しています。
画像ファイル以外をエラーにしたりなど、よく使われます。
参考:PHPでif文
他にも、ファイル名をより複雑にすることで、ファイル名の重複を避けたり、セキュリティ上のリスク回避にも繋がります。
以下の記事でご紹介しています。
ここでは割愛いたしますが、実装する際にはセキュリティ上の観点からも、エラーチェックはより厳重にする必要があります。
基本が分かったら、より実践的なプログラムにステップアップしてみましょう。
php.iniによる制限
HTML側でMAX_FILE_SIZE
を設定した場合でも、ブラウザの設定を出し抜くことは簡単です。
注意: ブラウザ側でこの最大値を出し抜くのは簡単なことなので、この機能を信頼して、 これより大きなサイズのファイルがブロックされることを前提にしてはいけません。 しかし、PHP 側の最大サイズの設定を欺くことはできません。
出典:PHPマニュアル
上記にもあるように、PHP側でもphp.ini
でサイズ制限などの設定があります。
(多くのサーバーではすでにデフォルトで制限されているかと思います。)
以下の項目が関係してくるので適切に設定しましょう。
項目 | 説明 | 初期値 |
---|---|---|
post_max_size | POSTする際のサイズ上限値。upload_max_filesize以上の値を設定する。 | 8M |
upload_max_filesize | アップロード時のファイルサイズ制限値で、post_max_sizeの値以下で設定する。MAX_FILE_SIZEはこの値以上は設定できない。 | 2M |
memory_limit | アップロード時の消費メモリ上限値。大きなファイルをアップロードする際は増やす。 | 128M |
max_execution_time | アップロード時の最大実行時間。あまり大きな値を設定すると、サーバーに負荷がかかりメモリ不足となることもある。 | 60(秒) |
max_file_uploads | アップロードできるファイル数の上限値。この数以上は一度にアップロードできない。 | 20 |
ファイルのアップロードの初歩的なところをご紹介しましたが、まだまだ奥が深い領域なので、別の機会にご紹介していきたいと思います。
とても分かりやすかったです。ありがとうございます!
そう言っていただけるととても嬉しいです。ありがとうございます。
これからも分かりやすさを第一に記事作成に取り組んでまいります。