はじめに
HTMLでファイルアップロード機能を作る基本は、<form>にmethod="post"とenctype="multipart/form-data"を指定し、<input type="file">で選ばれたファイルをサーバー側で検証して保存する流れです。画面側の制限だけでは偽装を防げないため、サイズ、MIMEタイプ、保存名の生成までサーバー側で扱います。
- HTML Living Standard / JavaScript ECMAScript 2024
- Google Chrome 126 / Firefox 127 / Safari 17
- PHP 8.3 / GD拡張が有効な環境
扱うコードは、HTMLフォーム、JavaScriptのFile API、PHPの$_FILESを組み合わせた実装です。表示や出力は環境設定、保存先の権限、PHPのupload_max_filesizeやpost_max_sizeで変わるため、サーバー設定とログも確認します。
HTMLフォームとファイルアップロードの基本
HTMLのファイルアップロードは、選択したファイルをHTTPリクエスト本文に入れて送る仕組みです。フォームにはmethod="post"とenctype="multipart/form-data"を組み合わせます。
MDNのform要素の公式ドキュメントでも、<form>は入力コントロールを送信する文書領域として説明されているのが基本です。GETはURLに値を含めるため、ファイルアップロードではPOSTが一般的です。
結果: 期待される表示は、ファイル選択欄とアップロードボタンです。送信すると、選択されたファイルが/uploadへmultipart/form-data形式で送られます。
name属性はサーバー側で受け取るキーです。MDNのaccept属性の公式ドキュメントでは、acceptは選択可能なファイル種別のヒントであり、最終検証はサーバー側で行う設計になります。
フォームの基本構造
フォームの主な要素は、送信範囲を示す<form>、説明文を結び付ける<label>、入力欄の<input>、送信操作の<button>です。よく使う属性やAPIを早見表にまとめますし、ここがポイントです。
| 項目 | 主な場所 | 役割 | 注意点 |
|---|---|---|---|
<form> | HTML | 送信対象の入力欄をまとめる | 入れ子構造にしない |
action | HTML | 送信先URLを決める | 空欄時は現在URLへ送られる |
method | HTML | HTTPメソッドを決める | ファイルではpostが一般的 |
enctype | HTML | 本文の符号化方式を決める | multipart/form-dataが必要 |
multipart/form-data | HTTP | ファイルと入力値を分割して送る | 境界文字列で各パートが区切られる |
<input> | HTML | 入力欄を作る | nameが受信キーになる |
type="file" | HTML | ファイル選択欄にする | ブラウザ標準UIが使われる |
name | HTML | サーバー側のキーになる | 複数時はfiles[]形式が使われる |
id | HTML | ラベルやJavaScriptから参照する | ページ内で重複させない |
<label> | HTML | 入力欄の説明を結び付ける | forとidを合わせる |
<button> | HTML | 送信ボタンを作る | type="submit"を明示する |
multiple | HTML | 複数選択を許可する | サーバー側も配列処理にする |
accept | HTML | 選択候補の種類を絞る | セキュリティ検証にはならない |
required | HTML | 未選択送信を抑制する | サーバー側でも未選択を判定する |
MAX_FILE_SIZE | HTML/PHP | 上限サイズを補助的に伝える | 信頼せずPHP側で再検証する |
File | JavaScript | 選択ファイルの情報を持つ | sizeやtypeを参照できる |
FileList | JavaScript | 選択されたファイル群を表す | 配列風だが通常の配列とは異なる |
files | JavaScript | 入力欄のファイル一覧を返す | 未選択時は長さが0になる |
FileReader | JavaScript | ブラウザ内でファイルを読む | 大容量ファイルでは負荷に注意する |
readAsDataURL() | JavaScript | 画像プレビュー用のURLを作る | Base64化でサイズが増える |
FormData | JavaScript | 非同期送信用の本文を作る | append()で値を追加する |
XMLHttpRequest | JavaScript | 進行状況を取得しやすい送信API | upload.onprogressを利用する |
fetch() | JavaScript | 非同期通信を行う | 標準だけではアップロード進捗を取りにくい |
<progress> | HTML | 進行状況を表す | valueとmaxを更新する |
$_FILES | PHP | アップロード情報を受け取る | errorを先に確認する |
tmp_name | PHP | 一時保存先を示す | 恒久保存前に移動が必要 |
UPLOAD_ERR_OK | PHP | エラーなしを表す | 値だけでなく保存処理も確認する |
move_uploaded_file() | PHP | 一時ファイルを保存先へ移す | 戻り値のfalseを処理する |
mime_content_type() | PHP | MIMEタイプを判定する | 拡張子だけに依存しない |
basename() | PHP | パス要素を除いた名前を得る | 保存名は生成し直すほうが堅い |
enctype、name、$_FILES、move_uploaded_file()がつながると、画面で選んだファイルを受信、検証、保存できます。
ファイルアップロードのHTMLコード例
単一ファイルのフォームは短く書けますが、送信先スクリプトや保存権限がなければ完了しません。
結果: 期待される表示は、必須入力のファイル選択欄と送信ボタンです。送信後、サーバー側のfile-upload.phpがuserfileという名前で受け取る構成になります。
問い合わせフォームやプロフィール画像登録にも応用できます。関連するフォーム設計は、HTMLで問い合わせフォームを作成する方法5選!も参考になるのが目安です。
ファイルアップロードの詳細な使い方
基本フォームの次は、複数選択、ドラッグアンドドロップ、事前チェックを組み合わせますし、ここがポイントです。ブラウザ側のチェックは補助なので、同じ条件をサーバー側でも再判定します。
サンプルコード1:基本的なファイルアップロードフォーム
複数ファイルに対応するには、multiple属性を追加し、name="files[]"のように配列で受け取れる名前にするのがポイントです。MDNのmultipleプロパティの公式ドキュメントでも、multipleは複数の値を扱う状態として説明されています。
結果: 期待される表示は、複数選択できるファイル入力欄です。ブラウザのファイル選択ダイアログで複数の画像を選び、まとめて送信できる構成になります。
サーバー側では$_FILES['files']['name']や$_FILES['files']['tmp_name']が配列になるため、error、size、typeを個別に確認します。
サンプルコード2:複数ファイルのアップロード対応
ドラッグアンドドロップは扱いやすい入力方法です。DataTransferから得たファイルをinput.filesに代入する挙動は、送信処理まで確認するのが一般的です。
結果: 期待される表示は、クリック選択とドラッグ操作の両方に反応するアップロード領域です。ファイルをドロップすると、隠した<input>へ選択情報が渡る構成になります。
dragoverで既定動作を止め、dropでevent.dataTransfer.filesを取得します。イベント設計は、『HTMLでアンカーリンクを活用する方法10選も関連するのが現実的です。
サンプルコード3:ドラッグアンドドロップでのアップロード対応
ファイルサイズと種類のチェックは送信前の補助です。file.typeはブラウザやOSの判定に依存するため、サーバー側のMIMEタイプ検証と組み合わせますが、これは押さえたい点です。
結果: 期待される表示は、画像形式を選びやすいファイル入力欄です。2MBを超えるファイルや許可外のMIMEタイプを選んだ場合、送信前に警告が出る想定です。
入力変化に応じた画面更新は、HTMLとJSを使ってカレンダーを作成・更新する方法10選にも通じます。
ファイルアップロード時のエラー処理と対処法
アップロード失敗の原因は、選択ファイル、通信、PHP設定、保存先権限に分かれますが、これは押さえたい点です。$_FILESのerror、tmp_name、size、保存処理の戻り値を確認するのが基本です。
結果: 期待される出力は、条件に合わないファイルを選んだ際の警告表示です。条件に合うファイルでは警告が出ず、フォーム送信へ進める構成になると整理できます。
accept、size、typeを画面側で見ても、PHPなどのサーバーサイド処理で再判定してください。エラーコードの理解と対応策
PHPでは、ファイルアップロード時の状態が$_FILES['field']['error']に入ります。PHPマニュアルのファイルアップロードエラーの公式ドキュメントには、UPLOAD_ERR_INI_SIZEやUPLOAD_ERR_PARTIALなどの意味が整理されていると理解できます。
結果: 期待される出力は、アップロード状態に応じたメッセージです。正常時は受け付け完了、サイズ超過や未選択時は原因別の文言が返る構成になります。
元のファイル名を使わず、random_bytes()とbin2hex()で保存名を生成すると覚えるとよいでしょう。拡張子やMIMEタイプの検証も加えますし、これが一つの目安です。
サーバー側のエラー対応
PHPが一時領域に置いたファイルを、アプリケーション管理の保存先へ移します。PHPマニュアルのmove_uploaded_file関数の公式ドキュメントでは、有効なアップロードファイルでない場合に移動しない仕様が示されていると考えられます。
結果: 期待される出力は、許可されたJPEGまたはPNGを受け付けた場合の完了メッセージです。許可外のファイル形式や保存失敗時は、原因に応じた文言に分岐します。
isset()で項目の有無を見てからerrorを判定し、MIMEタイプ検証後に保存します。
ファイルアップロードのセキュリティ対策
ファイルアップロード機能は、外部データをサーバーへ入れる入口です。種類、サイズ、保存先、公開方法を分けて設計すると言えるでしょう。
拡張子だけの判定、元ファイル名の再利用、Web公開ディレクトリへの直接保存はリスクが高くなるのがポイントです。.php、.html、.svgなどは許可リスト方式で扱います。
不正なファイルのアップロード防止策
不正ファイルの防止では、拡張子、MIMEタイプ、内容、保存先の分離を重ねて確認するのが基本です。ひとつの検証だけに依存しない構成にします。
ファイルタイプの検証
mime_content_type()やfinfo_file()で一時ファイルの内容からMIMEタイプを判定し、許可リストと照合するのが一般的です。
結果: 期待される出力は、許可外のMIMEタイプが送信された場合の拒否メッセージです。許可された種類の場合は、後続の保存処理へ進める構成になるのが基本です。
ファイルサイズの制限
ファイルサイズの制限は、画面側、PHP設定、アプリケーション側でそろえます。MAX_FILE_SIZEは補助であり、最終判定には使いません。
結果: 期待される表示は、画像を選択する入力欄です。MAX_FILE_SIZEはPHP側のエラー判定に関係しますが、信頼できる制限値として扱わない設計になります。
結果: 期待される出力は、3MBを超えるファイルが送信された場合の拒否メッセージです。サイズ内であれば、形式確認や保存処理へ進めますし、これが一つの目安です。
ファイル内容の検査
ファイル内容の検査では、拡張子やMIMEタイプだけでは見抜けない混入を確認します。画像として扱うファイルにPHPコードが含まれる場合も想定します。
結果: 期待される出力は、PHPコードらしき文字列を含むファイルに対する拒否メッセージです。実運用では、画像なら再エンコード、PDFなら専用の検査基盤を組み合わせる構成が考えられますが、覚えておくと役立つでしょう。
サーバー側での安全なファイル処理方法
安全な保存処理では、アップロード直後の一時ファイルをWebから直接実行されない領域へ移するのがポイントです。公開が必要なファイルだけを別経路に渡します。
一時ファイルの取り扱い
tmp_nameを直接表示せず、move_uploaded_file()でアップロード由来を確認しながら移動するのが現実的です。
結果: 期待される出力は、保存に失敗した場合のエラーメッセージです。保存できた場合は、生成された安全な名前でサーバー内の保存先へ移動する構成になるのが一般的です。
ディレクトリトラバーサル攻撃の防止
ユーザーが送ったファイル名には、パス区切り文字や制御文字が含まれる可能性があります。保存名はサーバー側で生成します。
結果: 期待される出力は、保存に失敗した場合のエラーメッセージです。保存できた場合は、危険な文字を置き換えた名前に日時と乱数を付けて保存する構成になります。
カスタマイズ例と応用
アップロード機能を使いやすくするには、画像プレビュー、進行状況表示、アップロード後処理を組み合わせます。動的な画面切り替えは、HTMLとCSSで手軽に作るスライドショーコピペ12選のUI構造も参考になるのが現実的です。
サンプルコード5:アップロードした画像を即時プレビュー
画像プレビューでは、選択ファイルをFileReaderで読み込み、<img>のsrcへ反映すると整理できます。
結果: 期待される表示は、画像を選択した直後にページ内へプレビュー画像が現れる状態です。未選択時は<img>が非表示のままになります。
readAsDataURL()で画像をData URLとして扱います。大きなファイルを多数プレビューする場合は件数を制限すると整理できると理解できます。
サンプルコード6:アップロード進行状況のバーを表示
XMLHttpRequestのupload.onprogressで送信済みバイト数を受け取り、<progress>を更新します。
結果: 期待される表示は、アップロード中に進行率が更新されるバーとテキストです。サーバーが200を返した場合は完了メッセージ、それ以外では失敗メッセージになります。
aria-live="polite"を置くと、支援技術へ状態変化を伝えやすくなります。
サンプルコード7:ファイルアップロード後の自動処理
アップロード後の自動処理では、画像リサイズやサムネイル生成がよく使われますが、覚えておくと役立つでしょう。PHPのGD拡張では、MIMEタイプに合わせて読み込み関数を切り替えますし、ここを基本と考えるとよいでしょう。
結果: 期待される出力は、画像処理を受け付けたことを示すメッセージです。JPEG、PNG、GIFのいずれかを受け取った場合に、元画像とサムネイル画像を保存する構成になります。
この例ではサムネイル保存にimagejpeg()を使うため、PNGやGIFの出力は要件に合わせて調整します。透過情報が必要なら、imagepng()やアルファチャンネル設定を使いると理解できると覚えるとよいでしょう。
プログラミングの豆知識
ファイルアップロードを理解するには、HTMLだけでなくHTTP、HTTPS、サーバー処理の流れも押さえます。HTML文書同士の関係は、HTMLとツリー構造をマスターする!初心者からプロまでわかる7つの完全ガイドが参考になります。
サーバーとのデータ交換についての深掘り
Webアプリケーションでは、ブラウザがリクエストを送り、サーバーがレスポンスを返すると覚えるとよいでしょう。MDNのPOSTメソッドの公式ドキュメントでも、ファイルや大量データを含むフォーム送信ではmultipart/form-dataが使われることが示されていると考えられます。
結果: 期待される出力は、POSTで送られたdataの内容をHTMLエスケープして返す文字列です。未送信の場合は空文字として扱われます。
$_SERVERでメソッドを確認し、$_POSTの値をhtmlspecialchars()でエスケープしていると考えられます。ファイルアップロードでも、出力時のエスケープと保存時の検証を分けますし、ここがポイントです。
HTTPとHTTPSの違いとセキュリティ
HTTPは暗号化されていない通信で、HTTPSはTLSで通信内容を保護します。HTTPSは通信経路の保護であり、サーバー到達後の検証、保存先権限、公開URL、ログ管理は別に設計すると言えるでしょう。
💡 Tips: HTTPS化、MIMEタイプ検証、保存名生成、非公開ディレクトリ保存は別々の対策です。アップロード機能のリスクに合わせて重ねます。
まとめ
HTMLでファイルアップロード機能を作る中心は、<form>、type="file"、multipart/form-data、サーバー側の$_FILES処理です。サイズ、MIMEタイプ、エラーコード、保存先、保存名をサーバー側で確認すると言えるでしょう。
関連記事
- 『HTMLでアンカーリンクを活用する方法10選
- HTMLとJSを使ってカレンダーを作成・更新する方法10選
- HTMLとCSSで手軽に作るスライドショーコピペ12選
- HTMLとツリー構造をマスターする!初心者からプロまでわかる7つの完全ガイド
- HTMLで問い合わせフォームを作成する方法5選!
※本記事は実在のエンジニア複数名で構成される Japanシーモア編集部が、AI支援を活用して作成・校正・公開しています。


