プロフィール画像のアップロードや、書類の添付に使う「ファイルを選択」ボタンは、<input type="file"> で作れます。受け付けるファイルの種類を絞る accept、複数選択を許す multiple、スマホでカメラを起動する capture など、属性を組み合わせて使い勝手を整えられます。この記事では、ファイル入力の基本から、選択されたファイルを JavaScript で読み取る方法、フォームで送信するときの注意点、そしてつまずきやすいポイントまで、初心者の方にも分かるように解説します。
目次
ファイル入力の基本
input 要素の type に file を指定すると、「ファイルを選択」ボタンが表示され、クリックすると OS のファイル選択ダイアログが開きます。何の入力かを示すために、label と結び付けておきます。
<label for="avatar">プロフィール画像</label>
<input type="file" id="avatar" name="avatar">
選択されたファイルは画面に表示されるわけではなく、ファイル名がボタンの横に出るだけです。実際にプレビューを出したり中身を扱ったりするには、後述する JavaScript やサーバー側の処理が必要になります。
accept で受け付ける種類を絞る
accept 属性を付けると、選択ダイアログで表示されるファイルの種類を絞り込めます。画像だけ、PDF だけ、といった指定ができ、利用者が誤ったファイルを選びにくくなります。指定方法は、拡張子(.png)・MIMEタイプ(image/png)・ワイルドカード(image/*)です。
<!-- 画像ファイル全般だけを受け付ける -->
<input type="file" name="photo" accept="image/*">
<!-- 拡張子で複数指定(カンマ区切り) -->
<input type="file" name="doc" accept=".pdf,.docx">
注意したいのは、accept はあくまで選択ダイアログの絞り込みの目安であり、強制ではない点です。利用者がダイアログ側の設定を変えれば、別の種類のファイルも選べてしまいます。種類の検証は、後述の JavaScript やサーバー側でも必ず行ってください。
multiple で複数のファイルを選ぶ
multiple 属性を付けると、一度に複数のファイルを選択できるようになります。値を持たない属性で、書くだけで有効になります。アルバムへの一括アップロードなどに便利です。
<!-- 複数の画像をまとめて選べる -->
<input type="file" name="photos" accept="image/*" multiple>
スマートフォンでは、capture 属性を付けると、ファイル選択の代わりにカメラやマイクを直接起動できます(capture="user" でフロントカメラ、capture="environment" で背面カメラ)。対応は端末やブラウザによりますが、その場で撮影してアップロードさせたいときに使えます。
選択されたファイルを JavaScript で読み取る
選択されたファイルの情報は、input 要素の files プロパティに FileList として入っています。各ファイルは File オブジェクトで、名前(name)・サイズ(size)・種類(type)を読み取れます。ファイルが選ばれた瞬間を捉えるには change イベントを使います。
const input = document.getElementById("avatar");
input.addEventListener("change", () => {
const file = input.files[0]; // 最初のファイル
if (!file) return; // 未選択なら何もしない
console.log(file.name); // 例: photo.png
console.log(file.type); // 例: image/png
console.log(file.size); // バイト数(数値)
});
multiple で複数選択した場合は、input.files をループで回せば1つずつ扱えます。size はバイト単位の数値なので、file.size > 5 * 1024 * 1024 のように比較すれば「5MBより大きいファイルを弾く」といったチェックができます。
画像のプレビューを表示する
選んだ画像をその場で表示するには、URL.createObjectURL() でファイルから一時的な URL を作り、img の src に設定します。サーバーへ送る前に確認させたいときに便利です。
const input = document.getElementById("avatar");
const preview = document.getElementById("preview");
input.addEventListener("change", () => {
const file = input.files[0];
if (!file) return;
// ファイルから一時URLを作って画像に表示する
preview.src = URL.createObjectURL(file);
});
フォームで送信するときの設定
ファイルをサーバーへ送る場合、form 側の設定が重要です。method="post" にしたうえで、enctype="multipart/form-data" を必ず指定します。この enctype が無いと、ファイルの中身は送信されず、ファイル名だけが送られてしまいます。
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" accept="image/*">
<button type="submit">アップロード</button>
</form>
サーバー側(PHP なら $_FILES)でファイルを受け取り、保存します。受け取ったあとは、種類・サイズ・拡張子の検証を行うことが大切です。クライアント側の accept やチェックはあくまで補助で、最終的な安全性はサーバー側の検証で担保します。
うまくいかないときの確認ポイント
ファイルが送信されないとき
もっとも多いのが、form に enctype="multipart/form-data" を付け忘れているケースです。また送信方式が get になっているとファイルは送れません。method="post" と enctype の両方を確認してください。input に name が無い場合も、サーバー側で受け取れません。
値を JavaScript で設定できないとき
セキュリティ上の理由から、input.value = "..." のように JavaScript からファイルの値を勝手に設定することはできません。利用者の操作なしに任意のファイルを選ばせるのを防ぐためです。選択を取り消したいときは input.value = "" で空にすることのみ可能です。
同じファイルを選ぶと change が起きないとき
一度選んだのと同じファイルをもう一度選んでも、値が変わらないため change イベントが発火しないことがあります。再選択を確実に拾いたいときは、処理の最後に input.value = "" で値をリセットしておくと、同じファイルでも毎回 change が起きるようになります。
まとめ
<input type="file"> は、ファイルのアップロード機能を作る基本の部品です。要点を整理します。
acceptで種類を絞り、multipleで複数選択、captureでカメラ起動。- 選択されたファイルは
input.files(Fileオブジェクト)から名前・サイズ・種類を取得できる。 - 画像プレビューは
URL.createObjectURL()で作った URL をimgに設定する。 - 送信には
method="post"+enctype="multipart/form-data"が必須。 acceptやクライアント側チェックは補助。検証はサーバー側でも必ず行う。
まずは accept="image/*" を付けたファイル入力を置き、change イベントでファイル名を表示するところから始めると、扱い方がつかめます。