HTMLのフォームからファイルをアップロードし保存する方法(PHP)
2025年 1月 9日 Posted 野々瀨(フロントエンドエンジニア)
ローカル上にあるファイルをWebサーバーへアップロードするには幾つかの方法があります。そのうちの一つとして、HTMLのフォームからファイルをアップロードする方法をご紹介します。ここではフォームの構築からWebサーバーへの保存方法までをご説明します。
前提条件
フォームを構築するのにHTMLの知識が必要ですが、Webサーバーへファイルを保存するためにはサーバーサイドの知識も必要です。ここでは、PHPというサーバーサイドの言語を用いますので、あらかじめ最低限の知識と環境をご用意ください。
HTMLでフォームを準備
ローカルからファイルを添付するためのフィールドと、送信ボタンを用意します。
<form action="upload.php" method="post" enctype="multipart/form-data">
<p><input type="file" name="select_file"></p>
<p><button>アップロード</button></p>
</form>
今回はPHPでファイル処理を行うスクリプトとして「upload.php」を用意しますので、form要素のaction属性に「upload.php」を指定しています。
ファイルをアップロードするため、method属性を「post」、enctype属性を「multipart/form-data」に指定します。
PHPでの処理
HTMLでform要素のaction属性にて指定したファイルパスでPHPファイルを作成します。次のコードを記述します。
<?php
// アップロードされたファイルの情報を取得
$upload_file_info = $_FILES['select_file'];
// 保存先ファイルパス
$save_file_path = 'upload/'.$upload_file_info['name'];
// 保存
if (move_uploaded_file($upload_file_info['tmp_name'], $save_file_path)) {
echo 'アップロードに成功しました。';
} else {
echo 'アップロードに失敗しました。';
}
?>
input[type="file"]要素は$_FILES
変数で情報を得ることができます。$_FILES
変数は2次元連想配列で、1次元目はinput[type="file"]要素のname属性値をキーに、2次元目はファイルの情報となっています。ここでは二つの情報を使用していて、ファイル名をname
キーから、一時的に保存されているファイルのテンポラリーファイルパスをtmp_name
キーから得ています。なお、input[type="file"]要素でname属性が同じ複数ある場合や、mutiple属性が付与されている場合、$_FILES
変数は3次元目に配列として選択されたファイル分のデータが格納されます。
move_uploaded_file
関数でテンポラリーに一時保存されているファイルを移動させます。第一引数にファイルのテンポラリーファイルのパスを、第二引数に移動先のファイルパスを指定します。戻り値は成功するとtrue
、失敗した場合はfalse
を返します。
【参考リンク】
- $_FILES:https://www.php.net/manual/ja/reserved.variables.files.php
- move_uploaded_file:https://www.php.net/manual/ja/function.move-uploaded-file.php
複数のファイルをアップロード
複数のファイルをアップロードする場合、まずHTML側はinput[type="file"]要素を増やすか、multiple属性を付与します。ここではinput[type="file"]要素にmultiple属性を付与することにします。また、name属性値は複数のデータとして扱うため、末尾に「[]」を指定します。
<form action="upload.php" method="post" enctype="multipart/form-data">
<p><input type="file" name="select_files[]" mutiple></p>
<p><button>アップロード</button></p>
</form>
次にPHPを複数ファイルに対応します。
<?php
// アップロードされたファイルの情報を取得
$upload_files_info = $_FILES['select_files'];
foreach ($upload_files_info['name'] as $i => $file_name) {
// 保存先ファイルパス
$save_file_path = 'upload/'.$file_name;
// 保存
if (move_uploaded_file($upload_files_info['tmp_name'][$i], $save_file_path)) {
echo 'アップロードに成功しました。<br>';
} else {
echo 'アップロードに失敗しました。';
}
}
?>
$_FILES
変数はname属性が同じ複数ある場合や、mutiple属性が付与されている場合、$_FILES
変数は3次元目に配列として選択されたファイル分のデータが格納されます。
Array(
[select_files] => Array(
[name] => Array(
[0] => sample1.txt
[1] => sample2.txt
)
[type] => Array(
[0] => text/plain
[1] => text/plain
)
[tmp_name] => Array(
[0] => /tmp/phpDAB9.tmp
[1] => /tmp/phpDABA.tmp
)
[error] => Array(
[0] => 0
[1] => 0
)
[size] => Array(
[0] => 123
[1] => 456
)
)
)
そのため、foreach
を使用して、例えばnameキーを繰り返し処理します。nameキーの情報はforeach
により得られますので、インデックス番号を利用してtmp_nameキーの情報を得ます。
PHPのアップロードの制限設定
PHPはアップロード時のファイルの最大容量など、php.iniでさまざまな設定がされています。ファイルのアップロードに関する設定は主に次の項目です。
項目 | 説明 |
---|---|
upload_max_filesize | ファイル一つあたりの最大容量。 |
post_max_size | POSTデータの最大容量(リクエストされたデータ全体の容量)。 |
upload_tmp_dir | アップロードされたファイルの一時保存先(テンポラリーディレクトリ)。 |
max_input_time | スクリプトを処理する前にフォームから受け入れたデータ(入力)を解析するための最大時間。 |
memory_limit | PHPが使用可能なメモリーの最大容量(上限)。 |
これらの設定は当然php.iniで設定変更可能ですが、.htaccessやPHPのini_set
関数で設定変更することもできます。ただし、設定変更が許可されている場合に限ります。
【おまけ】JavaScriptによる非同期アップロード
JavaScriptによる非同期でのアップロード方法をご紹介します。
HTMLとPHPは、これまでのコードそのままで問題ありません。次のJavaScriptを記述します。
document.forms[0].addEventListener('submit', event => {
event.preventDefault();
fetch(event.target.action, {
method : 'POST',
body : new FormData(event.target)
}).then(res => res.text()).then(result => {
alert(result);
});
});
form要素のsubmitイベントが発火された時に処理しています。
preventDefault
メソッドは標準のsubmit機能を無効化しています。
fetch
メソッドを使用してアップロードのためのリクエストを行います。第一引数にform要素のaction属性を指定し、第二引数のmethodプロパティに「POST」を、bodyプロパティにform要素のFormData
オブジェクトを指定します。FormData
オブジェクトはフィールドの情報が格納されています。
なお、フォームを送信するための「multipart/form-data」は、fetch API側で自動判別・設定するため、Content-Typeとして指定する必要はありません。