Parallels Desktop 15% OFFセール中 3月1日までClick!

【PHP入門】フォームでファイルをアップロードする方法

PHPでフォームからファイルをアップロードする方法

本記事では、PHPを使用してフォームからファイルをアップロードする方法について解説します。

Webアプリケーション開発において、ユーザからファイルを受け取る機能を実装する場合、セキュリティ上のリスクがあります。危ないです、怖いです、何を送りつけられるか分かったもんじゃありません。本記事では、HTMLフォームの作成方法やファイルを受け取る方法、セキュリティ対策について詳しく説明します。

目次

HTMLフォームの作成方法

ファイルをアップロードするためのHTMLフォームのコードは次のとおりです。

<form action="upload.php" method="post" enctype="multipart/form-data">
  <input type="file" name="thefile">
  <input type="submit" name="submit" value="アップロード">
</form>
  • <form>には以下の属性が必要です。
    • action : フォームの送信先URL(ファイルアップロード処理をするPHPスクリプト)を指定します。
    • method : postを指定します。
    • enctype : 送信データのエンコードタイプを指定します。ファイルを送信する場合は、multipart/form-dataを指定します。
  • <input>には以下の属性が必要です。
    • type : fileを指定して、ファイルをアップロードするための選択ボックスを表示します。
    • name : 任意の名前を指定します。

ブラウザでは次のように表示されます。

ファイルアップロードフォーム

PHPでファイルを受け取る方法

HTMLフォームから送信されたファイルを受け取るPHPスクリプトは次のようになります。

//ファイルを保存するディレクトリ
$upload_dir = './uploads/';

//アップロードされた一時ファイルを移動
if (move_uploaded_file($_FILES['thefile']['tmp_name'], $upload_dir . $_FILES['thefile']['name'])) {
  echo 'アップロードは成功しました';
//移動に失敗した場合
} else {
  echo 'アップロードは失敗しました';
}

アップロードされたファイルの情報は、スーパーグローバル変数$_FILESに格納されます。

HTMLフォーム<input type="file" name="thefile">から送信されたファイルの情報は次のような連想配列に格納されます。

$_FILES['thefile']['name']アップロードされたファイルの名前
$_FILES['thefile']['type']アップロードされたファイルのMIMEタイプ
$_FILES['thefile']['size']アップロードされたファイルのサイズ 単位はバイト
$_FILES['thefile']['tmp_name']アップロードされたファイルの一時保存パス
$_FILES['thefile']['error']アップロード時のエラーコード(エラーコードの説明
$_FILES['thefile']['full_path']アップロードされたファイルのフルパス(PHP 8.1.0以降で利用可能)

アップロードされたファイルは一時保存パス($_FILES['thefile']['tmp_name'])に保存されます。この一時ファイルは、スクリプトの実行が終了すると削除されてしまうので、move_uploaded_file()関数を使ってファイルを移動させる必要があります。

move_uploaded_file()関数の第1引数は一時保存パス、第2引数は移動先のパスです。移動に成功したらtrue、失敗したらfalseを返します。

また、この関数は第1引数のファイルがPOSTメソッドによりアップロードされた有効なファイルかどうかをチェックしてくれます。有効なアップロードファイルでなければfalseを返します。

有効なアップロードファイルかどうかを確認するためにis_uploaded_file()関数を使うべしという解説がまかり通っていますが、move_uploaded_file()関数がやってくれるので、必要ないと思いまーす。

セキュリティ対策

フォームから送信されるファイルはとても危険です。不正なファイルばかりです。この世にはあなたを騙そうとする人しかいないのです。なので、しっかりとセキュリティ対策をしましょう。

MIMEタイプのチェック

アップロードされるファイルのMIMEタイプをチェックすることで、想定外のファイルアップロードを防ぐことができます。MIMEタイプとは、ファイルの種類をあらわす情報です。

ならば$_FILES['thefile']['type']を使うんだなと思ったあなた、残念!この変数に格納されるMIMEタイプは簡単に偽装することができます。例えば、テキストファイルにfile.jpgという名前をつけてアップロードすると、MIMEタイプはimage/jpegになってしまいます。

そこで、Fileinfoクラスを使います。このクラスはファイルの拡張子ではなく内容からファイルの種類を推測してくれるので、より正確にMIMEタイプを判定できます。

//許可するMIMEタイプのリスト
$allowed_mime_types = [
  'image/gif',
  'image/jpeg',
  'image/png'
];

//MIMEタイプのチェック
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES['thefile']['tmp_name']);
if (!in_array($mime, $allowed_mime_types)) {
  exit('許可されていないファイル形式です');
}

//ファイルを保存するディレクトリ
$upload_dir = './uploads/';

//アップロードされた一時ファイルを移動
if (move_uploaded_file($_FILES['thefile']['tmp_name'], $upload_dir . $_FILES['thefile']['name'])) {
  echo 'アップロードは成功しました';
  //移動に失敗した場合
} else {
  echo 'アップロードは失敗しました';
}

ちなみに、おもなMIMEタイプには次のようなものがあります。

MIMEタイプ拡張子ファイルの種類
image/gif.gif画像
image/jpeg.jpg .jpeg画像
image/png.png画像
video/mpeg.mpg .mpeg動画
video/mp4.mp4動画
video/quicktime.mov .qt動画
video/x-msvideo.avi動画
audio/mpeg.mp3音声
audio/aac.m4a音声
audio/midi.mid .midi音声
audio/wav.wav音声
text/plain.txtテキスト
text/html.htm .htmlHTML
application/zip.zipアーカイブ
application/pdf.pdfPDFファイル
application/msword.docWordファイル
application/msexcel.xlsExcelファイル

ファイルサイズの制限

アップロードされるファイルのサイズを制限することで、サーバの負荷を軽減したり、ストレージの圧迫を避けることができます。

//許可するファイルサイズの上限
$max_file_size = 10 * 1024 * 1024; //10MB

//ファイルサイズをチェックする
if ($_FILES['thefile']['size'] > $max_file_size) {
  exit('ファイルサイズが大きすぎます');
}

//ファイルを保存するディレクトリ
$upload_dir = './uploads/';

//アップロードされた一時ファイルを移動
if (move_uploaded_file($_FILES['thefile']['tmp_name'], $upload_dir . $_FILES['thefile']['name'])) {
  echo 'アップロードは成功しました';
  //移動に失敗した場合
} else {
  echo 'アップロードは失敗しました';
}

ファイル名の変更

アップロードされるファイルの名前を変更することで、悪意のあるファイル名による攻撃を防ぐことができます。

また、move_uploaded_file()関数は、アップロードされたファイルの名前が重複していたらファイルを上書きします。これを防ぐためにもファイル名は変更したほうがよいでしょう。

//ファイル名を変更する
$extension = pathinfo($_FILES['thefile']['name'], PATHINFO_EXTENSION);
$new_file_name = uniqid() . '.' . $extension;

//ファイルを保存するディレクトリ
$upload_dir = './uploads/';

//アップロードされた一時ファイルを移動
if (move_uploaded_file($_FILES['thefile']['tmp_name'], $upload_dir . $new_file_name)) {
  echo 'アップロードは成功しました';
  //移動に失敗した場合
} else {
  echo 'アップロードは失敗しました';
}

ファイルアップロードに関連するPHPの設定

ファイルのアップロード処理に影響を与えるPHPの設定には、次のようなものがあります。

設定名説明初期値設定場所
upload_max_filesizeアップロードされるファイルの最大サイズ2MBPHP_INI_PERDIR
post_max_sizePOSTメソッドで送信するデータの最大サイズ8MBPHP_INI_PERDIR
max_file_uploads同時にアップロードできるファイルの最大数20PHP_INI_PERDIR
upload_tmp_dirアップロードされるファイルの一時保存ディレクトリNULL (/tmp)PHP_INI_SYSTEM
file_uploadsファイルアップロードを許可するかどうか1 (有効)PHP_INI_SYSTEM
max_input_timeアップロードされたファイルの処理にかかる最大時間-1 (30秒)PHP_INI_PERDIR
max_execution_timeスクリプトの実行にかかる最大時間30PHP_INI_ALL
設定場所
  • PHP_INI_PERDIR: ini_set(), .user.ini で設定可能
  • PHP_INI_SYSTEM: php.ini, httpd.conf で設定可能
  • PHP_INI_ALL: どこでも設定可能

これらの設定は、php.iniファイルやini_set()関数などで変更することができます。

でわでわ

プログラミング学習、お疲れさまです

プログラミングの独学に行き詰まっていませんか?誰かに相談したい、もっと効率よく学びたいなら、プログラミングスクールを検討してみてください。

PHPでフォームからファイルをアップロードする方法

この記事が気に入ったら
いいね または フォローしてね!

シェアしてね

コメント

コメントする

目次