問い合わせフォームに画像やPDFを添付できる欄を作りたい。そんなときに使うのが、HTMLの<input type="file">です。
ただし、画面でファイルを選べても、それだけでは送信や保存はされません。「端末で選ぶ」「サーバーへ送る」「受け取って保存する」を分けると、どこまでできているかを判断しやすくなります。
この記事では、ファイル選択欄の基本とaccept・multiple・requiredの役割を、コードと図で整理します。まず送信しない練習で選択数や名前を確認し、その後に送信フォームの設定と受信側に必要な確認を学びましょう。サーバー側の保存プログラムの作成は扱いません。
input type="file"の役割と基本の書き方- ファイル送信に必要な
name・method・enctype acceptで選択候補を絞る書き方と注意点multipleとFileListで複数ファイルを扱う考え方required・C:\fakepath\・サーバー側検証の意味
HTMLのファイルアップロードと3つの処理
<input type="file">は、利用者の端末からファイルを選ぶためのフォームコントロールです。最小の書き方は次のとおりです。
<label for="avatar">プロフィール画像</label>
<input type="file" id="avatar" name="avatar" />
このHTMLを表示すると、ブラウザーがファイル選択用のボタンや選択状態を示す欄を用意します。見た目やボタンの文言、選択操作はOSやブラウザーによって異なります。
input type="file"はファイルを選ぶ入口です。選択しただけでは送信・保存されません。
選択・送信・検証と保存の流れ
利用者の操作と、ブラウザー・サーバーの役割を3つに分けて見てみましょう。

HTMLは選択欄と送信先を指定し、ブラウザーが選択ファイルをフォームデータに含めて送ります。受信後の検証と保存は、PHP、Node.js、Rubyなどで作るサーバー側のプログラムが担当します。
最初に覚えたい3つの言葉
- ファイルピッカー:端末内のファイルを選ぶためにOSやブラウザーが表示する画面
- フォームデータ:送信時にブラウザーが組み立てる入力項目とファイルの集まり
- サーバー側:送信されたデータを受け取り、検証や保存を行う処理
「選べる状態」と「保存できる状態」を分けて考えましょう。 HTMLで入力欄を置いただけでは完成ではなく、送信先とサーバー側の受け取り処理まで揃って初めてアップロード機能になります。
フォーム全体の部品を先に確認したい場合は、HTMLのform・input・label・buttonの基本も参考にしてください。
input type="file"の基本的な書き方
実際にファイルを送るには、formの設定も必要です。次は1件のファイルを送る最小構成です。/uploadは説明用のURLで、受信プログラムがなければ保存まで試せません。
<form action="/upload" method="post" enctype="multipart/form-data">
<label for="avatar">プロフィール画像</label>
<input type="file" id="avatar" name="avatar" />
<button type="submit">アップロードする</button>
</form>
この例の/uploadは説明用の送信先です。HTMLだけでは保存処理を実行できないため、実際にはサーバー側へ/uploadを処理するプログラムを用意します。
type属性の役割
type属性へfileを指定すると、テキストではなくファイルを選ぶコントロールになります。type="text"のように文字列を直接入力する欄とは役割が異なります。
idとlabelの関連付け
id="avatar"とlabelのfor="avatar"を一致させると、ラベルと入力欄を関連付けられます。画面に「プロフィール画像」と書くだけでなく、コード上でも対応を示せるため、利用者が目的を理解しやすくなります。
nameと送信項目名
name="avatar"は、送信先がファイルを見分けるための項目名です。idだけでは送信項目名になりません。通常のフォーム送信では、nameのない入力欄やdisabledで無効にした入力欄は送信対象から外れます。
method="post"とenctype="multipart/form-data"
通常のHTMLフォームでファイル本体を送る場合は、method="post"とenctype="multipart/form-data"を指定します。multipart/form-dataは、文字入力とファイル本体を区切りながらリクエスト本文へ入れる形式です。enctypeを省略した既定の形式では、ファイル本体を送れません。
ファイル送信では、name・post・multipart/form-dataをセットで確認します。送信先のactionも受信側の仕様に合わせます。
| 属性 | 役割 | 初心者の確認ポイント |
|---|---|---|
type="file" | ファイル選択欄にする | textなど別のtypeになっていないか |
id | 要素を識別する | labelのforと一致しているか |
name | 送信項目名にする | 空欄・付け忘れがないか |
method="post" | リクエスト本文で送る | getのままになっていないか |
enctype="multipart/form-data" | ファイルを含む送信形式にする | スペルを含めformへ指定したか |
action | 送信先を指定する | 受信処理のURLと一致するか |
入力欄のtype・name・valueの関係は、HTMLのinputタグのtype・name・value属性で確認できます。
accept属性と選択候補の指定
accept属性は、ファイルピッカーで選択候補にしたいファイル形式をブラウザーへ伝える属性です。
<input type="file" name="avatar" accept="image/*" />
値には、拡張子やMIMEタイプをカンマ区切りで指定できます。MIMEタイプはimage/pngのようなファイル形式の識別名です。image/*の*は画像全般を示します。
| 目的 | acceptの例 | 意味 |
|---|---|---|
| 画像全般 | image/* | ブラウザーが画像として扱う形式 |
| JPEGとPNG | .jpg,.jpeg,.png | 指定した拡張子 |
.pdf,application/pdf | PDFの拡張子とMIMEタイプ | |
| 音声全般 | audio/* | 音声形式全般 |
| 動画全般 | video/* | 動画形式全般 |
たとえば、JPEG・PNG・PDFを候補にする場合は次のように書けます。
<input
type="file"
name="attachment"
accept=".jpg,.jpeg,.png,.pdf,image/jpeg,image/png,application/pdf"
/>
指定内容の詳しい形式は、MDNのaccept属性リファレンスで確認できます。
acceptとサーバー側検証の違い
多くのファイルピッカーでは、条件に合わないファイルを薄く表示したり候補から外したりします。しかし、利用者が表示条件を変更できる場合があり、送信データ自体もブラウザー外から作れます。
acceptは選択ミスを減らすための補助です。安全性はサーバー側でも確認します。

acceptは「選びやすさ」、サーバー側検証は「受け入れてよいか」の判断です。 両方を用意し、同じ許可方針を画面の説明とサーバー処理で共有すると、使いやすさと安全性を両立できます。
multiple属性と複数ファイルの選択
multipleは、複数ファイルの選択を許可する論理属性です。論理属性は「書いてあるかどうか」で有効・無効が決まります。無効にしたいときは属性自体を取り除きます。multiple="false"と書いても無効にはなりません。
<input type="file" name="photos" accept="image/*" multiple />
multipleなしでは、一つの入力欄で選べるファイルは最大1件です。付けると複数件を選べますが、1件だけでも構いません。複数選択の操作はOSや端末によって異なります。
<!-- 1件だけ -->
<input type="file" name="photo" />
<!-- 複数件 -->
<input type="file" name="photos" multiple />
filesとFileListから選択数を取得する
選択されたファイルは、入力欄のfilesプロパティからFileListとして取得できます。lengthは選択数で、未選択なら0です。各ファイルのnameは名前、sizeはバイト単位の容量、typeはMIMEタイプです。typeが空になる場合もあるため、これだけで形式や安全性を判断しません。
<label for="photos">写真を選択</label>
<input id="photos" name="photos" type="file" accept="image/*" multiple />
<p id="result">まだ選択されていません</p>
<script>
const input = document.querySelector("#photos");
const result = document.querySelector("#result");
input.addEventListener("change", () => {
const files = input.files;
result.textContent = `${files.length}件のファイルを選択しました`;
});
</script>
![multipleなしは最大1件、ありは複数件を選択できる。files[0]は最初のファイル、files.lengthは選択数](https://hoai.jp/wp-content/uploads/2026/09/A042-html-file-upload-FIG04-multiple-filelist-v2.png)
複数ファイルを送ると、同じnameに対して複数のファイル項目が含まれます。photos[]のような角括弧が必要か、どのデータ構造で受け取るかはサーバー側の言語やフレームワークで異なります。利用中のフレームワークのアップロード仕様を確認してください。
FileListの基本はMDNのFileListリファレンスで確認できます。
required・value・C:\fakepath\の意味
ファイル入力でもrequiredで選択を必須にできます。通常のフォーム送信で制約検証が働く場合、1件も選択していなければブラウザーが送信を止めます。novalidateの指定や独自のJavaScript送信などで検証を通らない場合があるため、受信側でも確認します。
<input type="file" name="resume" accept=".pdf" required />
multipleと一緒に使った場合も、requiredが確認するのは「少なくとも1件選ばれているか」です。形式や容量、安全性は確認しないため、サーバー側の検証は必要です。
valueとC:\fakepath\の見え方
ファイルを選ぶと、JavaScriptのinput.valueに次のような文字列が見える場合があります。
C:\fakepath\photo.jpg
C:\fakepath\は、実際の保存場所ではありません。利用者のフォルダー位置を公開しないための表現です。ファイル名や選択数はvalueを分解せず、filesから取得します。
const input = document.querySelector('input[type="file"]');
input.addEventListener("change", () => {
const firstFile = input.files[0];
if (!firstFile) return; // 未選択ならここで終える
console.log(firstFile.name);
console.log(firstFile.size);
console.log(firstFile.type);
});
このコードは、ファイル入力欄より後に置く<script>内で使います。選択の変更後に読み取り、未選択なら処理を終えるため、存在しないファイルの名前を読み取るエラーを防げます。なお、JavaScriptから任意の非空ファイルパスをvalueへ設定して事前選択することはできません。
送信せずに試せるファイル選択の練習
次のコードは、HTMLファイルをブラウザーで開くだけで試せます。ファイルをサーバーへ送信する処理はありません。JavaScriptが有効なブラウザーで、個人情報を含まない練習用の画像やPDFを使ってください。
下のコード全体をテキストエディターへ貼り付け、UTF-8でfile-selection.htmlとして保存します。末尾が.txtにならないようにし、ブラウザーで開きます。
何も選ばず「選択を確認する」を押すと、選択を求める案内が表示されます。次に1件、複数件の順で選び、画面の件数とファイル名が選んだ内容と一致するか確認します。
「クリア」を押すと、選択と一覧が空になり、0件へ戻ります。続けてmultipleをコードから削除して保存・再読み込みすると、一度に選べる件数の違いを確認できます。
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ファイル選択の練習</title>
</head>
<body>
<h1>ファイル選択の練習</h1>
<p>この例はファイルを送信しません。</p>
<label for="attachments">添付ファイル(JPEG・PNG・PDF、必須、複数可)</label>
<input
id="attachments"
name="attachments"
type="file"
accept=".jpg,.jpeg,.png,.pdf,image/jpeg,image/png,application/pdf"
multiple
required
/>
<button type="button" id="check">選択を確認する</button>
<button type="button" id="clear">クリア</button>
<p id="result" aria-live="polite">0件:まだ選択されていません</p>
<ul id="file-list"></ul>
<script>
const input = document.querySelector("#attachments");
const result = document.querySelector("#result");
const list = document.querySelector("#file-list");
function showFiles() {
list.replaceChildren();
result.textContent = input.files.length === 0
? "0件:まだ選択されていません"
: `${input.files.length}件を選択中(送信していません)`;
for (const file of input.files) {
const item = document.createElement("li");
item.textContent = `${file.name}(${file.size} bytes)`;
list.append(item);
}
}
input.addEventListener("change", showFiles);
document.querySelector("#check").addEventListener("click", () => {
input.reportValidity();
showFiles();
});
document.querySelector("#clear").addEventListener("click", () => {
input.value = "";
showFiles();
});
</script>
</body>
</html>
確認ボタンはtype="button"で、reportValidity()によりrequiredの未選択チェックを呼び出します。この練習にはformも送信ボタンもありません。JavaScriptが無効なら件数表示やボタンの処理は動きません。
ファイル名はtextContentで文字として表示し、HTMLとして解釈させません。ここで確認できるのは選択した名前・容量・件数であり、ファイルの安全性やサーバーへの保存成功ではありません。
サーバーへ送るフォームの実装例
ここからは、受信処理を用意した学習用サーバーで使うHTMLです。actionのURLは説明用なので、実際にPOSTを受け付ける自分の送信先へ変更してください。静的なHTMLを表示するだけのサーバーでは、アップロードを受け付けられない場合があります。
画像を1件だけ必須で送る例
<form action="/profile/avatar" method="post" enctype="multipart/form-data">
<label for="avatar">プロフィール画像(JPEGまたはPNG、必須)</label>
<input
type="file"
id="avatar"
name="avatar"
accept=".jpg,.jpeg,.png,image/jpeg,image/png"
required
/>
<button type="submit">画像を送信する</button>
</form>
入力欄のname="avatar"に合わせ、受信側でもavatarという項目のファイルを処理します。acceptと同じ許可形式を受信側でも検証してください。
画像・PDFを複数送る例
<form action="/support/attachments" method="post" enctype="multipart/form-data">
<label for="attachments">添付ファイル(JPEG・PNG・PDF、複数可)</label>
<input
type="file"
id="attachments"
name="attachments"
accept=".jpg,.jpeg,.png,.pdf,image/jpeg,image/png,application/pdf"
multiple
/>
<button type="submit">添付ファイルを送信する</button>
</form>
この例はrequiredを付けていないため、添付は任意です。必須にするなら画面の説明と属性をそろえ、受信側も同じ条件にします。受信側ではattachmentsの複数ファイルを1件ずつ検証し、保存できた件数やエラーを利用者へ返します。
サーバー側で必要なファイルの確認
HTMLの属性やJavaScriptの確認は操作ミスを減らす補助です。受信側では、サービスに必要なファイルだけを許可する方針で、次の確認を組み合わせます。ここでは設計上の確認項目を示し、受信プログラムそのものは扱いません。
- 利用者にアップロードを許可する条件を確認する(会員限定ならログインと権限も確認)
- 許可する拡張子を限定する
- 申告されたMIMEタイプだけを信用せず、内容やファイル署名も確認する
- 1件あたりの容量、件数、合計容量を制限する
- 保存名をアプリ側で生成し、危険な文字や上書きを避ける
- 可能なら公開ディレクトリー外または別ホストへ保存する
- 必要に応じてマルウェア検査や文書の無害化を行う。認証情報を使う機能では、別のサイトから意図しない送信をさせる攻撃を防ぐCSRF対策も行う
MIMEタイプは形式の識別名、ファイル署名は内容の先頭などにある形式の手がかりです。送信されたContent-Typeも偽装できるため、一つの判定だけに頼りません。詳しい設計はOWASPのFile Upload Cheat Sheet(英語)で確認できます。
受信後は、エラー理由を利用者へ分かる言葉で返します。「アップロードに失敗しました」だけでなく、「PDFは10MBまでです」のように、次に直す内容を示すと再操作しやすくなります。ただし、サーバー内部の保存場所や詳細な例外情報は公開しません。
ファイルが送れないときのチェックポイント
アップロードで迷ったら、ファイル選択欄、送信リクエスト、サーバー処理のどこで止まっているかを分けて確認します。
| 症状 | 主な確認箇所 | 対処 |
|---|---|---|
| 選びたいファイルが候補に出ない | accept | 拡張子・MIMEタイプ・カンマ区切りを見直す |
| 送信データにファイルがない | nameと所属先 | nameとフォームへの所属(内側に置くかform属性で関連付け)、disabledを確認 |
| サーバーで空になる | methodとenctype | POST・送信形式・受信処理・容量上限を確認 |
| 複数選んだのに1件だけ保存される | multipleと受信処理 | multipleとサーバー側の複数受け取り処理を確認 |
| 未選択でも送信できる | required | 対象inputにrequiredがあるか、独自送信処理を確認 |
C:\fakepath\が表示される | valueの仕様 | 実パスではないため、filesから名前などを取得 |
Networkで送信内容と応答を確認する
Network(ネットワーク)はブラウザーの開発者ツールにある通信の記録画面です。自分が管理する学習用の受信環境で、ページを右クリックして「検証」を開き、Networkを表示してから送信します。ページ移動がある場合は、送信前にPreserve log(ログを保持)を有効にします。actionに対応する最初のリクエストを選び、送信先URL、POST、multipart/form-data、ファイルの項目名を確認してください。
Payload(送信データ)の表示方法はブラウザーによって異なり、ファイル本体がそのまま表示されないこともあります。項目名と選択状態を確認したら、Status(応答状態)とResponse(応答内容)、必要に応じて受信側の記録へ進みます。送信項目が見えることやHTTP 200だけでは、保存完了とは判断できません。保存結果まで確認しましょう。項目の見方はChrome DevToolsのNetworkリファレンスも参考になります。
よくある質問
- ファイルを選んだ瞬間にアップロードされますか?
-
通常のフォームでは、選択しただけでは送信されません。送信ボタンでフォームを送るか、JavaScriptで自動アップロード処理を実装したときにリクエストが発生します。意図しない自動送信にならないよう、画面上で開始タイミングを伝えてください。
- accept="image/*"とaccept=".jpg"はどう使い分けますか?
-
image/*は画像全般、.jpgはJPEGの拡張子に候補を絞る指定です。必要な形式が限定される場合は拡張子とMIMEタイプを併記し、画像全般を受け付ける場合はimage/*を使います。どちらの場合もサーバー側で実際の内容を確認してください。 - multipleで選んだファイルはサーバーで配列になりますか?
-
HTMLの送信では、同じ
nameに対する複数のファイル項目になります。配列やリストとして受け取る書き方は、サーバー側の言語やフレームワークで異なります。利用中の公式ドキュメントで複数ファイル受信の方法を確認してください。 - C:\fakepath\と表示されるのはエラーですか?
-
エラーではありません。利用者の実際のフォルダー位置をページへ公開しないためのブラウザー仕様です。ファイル名、容量、種類は
input.files内のFileオブジェクトから確認します。 - requiredだけでファイル形式や容量も確認できますか?
-
できません。
requiredは未選択かどうかを確認します。形式、容量、内容、安全性はサーバー側で検証し、必要なら画面にも許可条件とエラーを表示してください。 - JavaScriptであらかじめローカルファイルを選択できますか?
-
ページ側から任意の非空ファイルパスを
valueへ設定して事前選択することはできません。利用者自身の選択なしに端末内ファイルへアクセスさせないための制限です。再送フォームでも、利用者にもう一度選択してもらいます。 - ファイル選択ボタンをCSSで自由に変更できますか?
-
::file-selector-buttonでボタン部分を装飾できるブラウザーがあります。ただし、選択操作そのものを壊さないこと、キーボード操作やフォーカス表示を残すこと、ラベルと許可条件を見える形で示すことが重要です。 - ドラッグ&ドロップでも同じファイルを扱えますか?
-
扱えます。ドラッグ&ドロップでは
DataTransfer.filesからFileListを取得します。ただし、ドロップ領域だけにせず通常のinput type="file"も残すと、キーボード利用や対応環境の違いを補えます。受信後のサーバー側検証は同じです。
まとめ
input type="file"は、利用者が端末からファイルを選ぶためのフォームコントロールです。
- 基本形は
<input type="file" id="..." name="..."> - ファイル送信ではPOSTと
multipart/form-dataを指定する acceptは選択候補を示すヒントで、検証の代わりにはならないmultipleを付けると複数選択でき、JavaScriptではfilesからFileListを受け取るrequiredは未選択を防ぐが、形式や容量は確認しないC:\fakepath\は実際のフォルダー位置ではない- サーバー側で種類、容量、権限、名前、保存場所などを多層に確認する
まずは送信しない練習例を使い、未選択、1件選択、複数選択、クリアの結果を確かめてください。実際のアップロードへ進むときは、受信先と項目名を合わせ、サーバー側の検証と保存結果まで確認しましょう。
目的別に次の記事を選ぶ
送信先URLと項目の関係を確認したい場合は、action・methodの基本へ進みましょう。

GETとPOSTの違いや、Networkで送信内容を確認する流れを整理したい場合は、次の記事が役立ちます。


