<input type="file">
<input>
要素の type="file"
型は、ユーザーが一つまたは複数のファイルを端末のストレージから選択することができるようにします。選択されると、ファイルはフォーム投稿を使用してサーバーにアップロードしたり、JavaScript コードとファイル API を使用して操作したりすることができます。
試してみましょう
値
ファイル入力欄の value
属性には、選択されたファイルへのパスを表す文字列が入ります。ファイルが選択されていない場合は、値は空文字列 (""
) になります。ユーザーが複数のファイルを選択すると、value
は選択されたファイルのリストのうち最初のファイルを表します。その他のファイルは input 要素の HTMLInputElement.files
プロパティを使って得ることができます。
メモ: 文字列には常に C:\fakepath\
の接頭辞が付き、ファイルの実際のパスにはなりません。疑わしいソフトウェアがユーザーのファイル構造を推測することを防止するためです。
追加の属性
すべての <input>
に共通の属性に加え、 file
型の入力欄は次の属性にも対応しています。
accept
accept
属性の値は文字列で、ファイル入力欄が受け付けるファイル型を定義します。この文字列は 固有ファイル型指定子 をカンマで区切ったリストです。指定されたファイル型が複数の方法で識別されることがあるので、指定された形式のファイルが必要な場合は一連の型指定子を提供するといいでしょう。
例えば、 Microsoft Word ファイルを識別する方法がいくつもあるので、 Word ファイルを受け付けるサイトは次のように <input>
を使用することがあります。
<input
type="file"
id="docpicker"
accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
capture
capture
属性は文字列で、 accept
属性で入力が画像または映像データであると示した場合、これらのデータを取り込むためにどのカメラを使用するかを指定します。 user
の値では、ユーザーの方を向いているカメラやマイクを使用します。 environment
は外側を向いたカメラやマイクを使用します。この属性がない場合、ユーザーエージェントは何をするかを自分で自由に決めます。要求された方向が有効ではない場合、ユーザーエージェントは推奨される既定のモードで代用します。
メモ: capture
は以前は論理値であり、存在した場合、ファイル入力を要求する代わりに、カメラやマイクなどその端末のメディア取り込み機器を使用するように要求していました。
multiple
multiple
論理属性が指定されていると、ファイル入力欄はユーザーに複数のファイルを選択することを許します。
標準外の属性
上記に挙げた属性に加え、以下の標準外の属性が一部のブラウザーで利用できます。実装していないブラウザーではコードが機能する可能性が制限されるため、できれば使用することを避けてください。
webkitdirectory
論理型の webkitdirectory
属性は、もし存在する場合は、ファイル選択インターフェイスでユーザーがディレクトリーのみを選択することができることを示します。詳しい解説と例については HTMLInputElement.webkitdirectory
を参照してください。
メモ: webkitdirectory
はもともと WebKit ベースのブラウザー向けのみに実装されたものですが、 Microsoft Edge や Firefox 50 以降でも使用できます。しかし、比較的広く対応されていますが、まだ標準になっておらず、代替手段がない限りは使用するべきではありません。
固有ファイル型指定子
固有ファイル型指定子は文字列で、 file
型の <input>
要素でユーザーが選択することができるファイルの種類を記述します。それぞれの固有ファイル型指定子は、次の形のうち一つを取ることができます。
- 有効なファイル拡張子で、大文字小文字の区別なく、ピリオド (".") 文字で始まるもの。例えば、
.jpg
,.pdf
,.doc
など。 - 有効な MIME タイプ文字列で、拡張子のないもの。
- 文字列
audio/*
で「任意の音声ファイル」を意味する。 - 文字列
video/*
で「任意の動画ファイル」を意味する。 - 文字列
image/*
で「任意の画像ファイル」を意味する。
accept
属性は、これらの固有ファイル型指定子を 1 つ以上含む文字列を取ります。例えば、ファイル選択ダイアログが画像として表示することができるコンテンツを必要としており、標準の画像形式と PDF ファイルの両方を含める場合、このようになります。
<input type="file" accept="image/*,.pdf" />
ファイル入力欄の使用
基本的な例
<form method="post" enctype="multipart/form-data">
<div>
<label for="file">アップロードするファイルを選択してください</label>
<input type="file" id="file" name="file" multiple />
</div>
<div>
<button>送信</button>
</div>
</form>
これは以下のような出力になります。
ユーザーの端末やオペレーティングシステムに関わらず、ファイル入力欄にはユーザーがファイルを選択することができるファイル選択ダイアログを開くボタンがあります。
上記のように、 multiple
属性を含めると、複数のファイルを一度に選択することができることを指定します。ユーザーはファイル選択ダイアログから、プラットフォームが許す方法(例えば、 Shift または Control を押しながらクリック)によって、複数のファイルを選択できます。ユーザーに <input>
あたり 1 つのファイルを選択させたい場合は、 multiple
属性を省略してください。
選択されたファイルの情報の取得
選択されたファイルは、この要素の HTMLInputElement.files
プロパティで返され、これは File
オブジェクトのリストを含む FileList
オブジェクトです。 FileList
は配列のようにふるまうので、 length
プロパティを使用して選択されたファイルの数を取得することができます。
それぞれの File
オブジェクトは以下のような情報を持っています。
name
-
ファイルの名前です。
lastModified
-
ファイルが最後に変更された日時を表す数値で、 UNIX 時刻 (1970 年 1 月 1 日午前 0 時) からの経過ミリ秒数です。
lastModifiedDate
非推奨-
ファイルが最後に変更された日時を表す
Date
オブジェクトです。これは非推奨であり使うべきではありません。代わりにlastModified
を使用してください。 size
-
バイト数によるファイルサイズです。
type
-
ファイルの MIME タイプです。
webkitRelativePath
Non-standard-
ディレクトリー選択ダイアログ (つまり、
webkitdirectory
属性が設定されているfile
ダイアログ) で選択されたベースディレクトリーからのファイルの相対パスを表す文字列です。これは標準外なので使用するには注意してください。
メモ: 最近のブラウザーはすべて、 HTMLInputElement.files
の値を取得だけではなく設定もできるようになっています。これが最も後に追加されたのは Firefox で、バージョン 57 で追加されました (see Firefox バグ 1384030)。
受け付けるファイル型の制限
ふつう、ユーザーが自由な形式のファイルを選択できるようにはしたくないでしょう。代わりに、特定の形式のファイルを選択させたいでしょう。例えば、ファイル入力欄でユーザーにプロフィールファイルをアップロードさせるのであれば、おそらく JPEG または PNG のようなウェブに互換性がある画像形式を選択させたいでしょう。
受付可能なファイル形式は accept
属性で、受け付けるファイルの拡張子または MIME タイプいくつか例を示します。
accept="image/png"
またはaccept=".png"
— PNG ファイルを受け付けます。accept="image/png, image/jpeg"
またはaccept=".png, .jpg, .jpeg"
— PNG または JPEG ファイルを受け付けます。accept="image/*"
—image/*
の MIME タイプである任意のファイルを受け付けます。 (多くのモバイル端末では、この場合にユーザーがカメラで写真を撮ることもできるようになっています。)accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
— MS Word 文書と思われるファイルをすべて受け付けます。
もっと複雑な例を見てみましょう。
<form method="post" enctype="multipart/form-data">
<div>
<label for="profile_pic">アップロードするファイルを選択してください</label>
<input
type="file"
id="profile_pic"
name="profile_pic"
accept=".jpg, .jpeg, .png" />
</div>
<div>
<button>送信</button>
</div>
</form>
これは前回の例と似た外見の出力をします。
同じように見えるかもしれませんが、この入力欄でファイルを選択しようとすると、このファイル選択ダイアログでは accept
の値で指定されたファイル形式しか選択できません。 (細かい動きはブラウザーやオペレーティングシステムによって異なります)。
accept
属性は選択されたファイルの形式を検証しません。単にブラウザーにユーザーが正しいファイル形式を選択するためのガイドするためのヒントを出すだけです。 (多くの場合) ユーザーがファイル選択ダイアログオプションを切り替えることで、ファイル選択ダイアログがこの設定を上書きして任意のファイルを選択することができるので、不正なファイル形式を選択する可能性があります。
このため、 accept
属性は適切なサーバー側の検証でバックアップする必要があることを意識しておいてください。
キャンセルの検出
cancel
イベントは、ユーザーが選択を変更せず、前回選択したファイルを再選択した場合に発行されます。 cancel
イベントはファイルピッカーダイアログが "cancel" ボタンや escape キーによって閉じられたり、取り消されたりした場合にも発行されます。
例えば、次の例はユーザーがファイルを選択せずにポップアップを閉じた場合にコンソールにログ出力します。
const elem = document.createElement("input");
elem.type = "file";
elem.addEventListener("cancel", () => {
console.log("Cancelled.");
});
elem.addEventListener("change", () => {
if (elem.files.length == 1) {
console.log("File selected: ", elem.files[0]);
}
});
elem.click();
注
-
スクリプトからファイル選択ダイアログの値を設定することはできません。 — 以下のようにしても効果はありません。
jsconst input = document.querySelector("input[type=file]"); input.value = "foo";
-
<input type="file">
を使用してファイルが選択された場合、セキュリティ上の理由から、元のファイルへの実際のパスがvalue
属性上では見えないようになっています。その代わりに、ファイル名の先頭にC:\fakepath\
を追加したものが表示されます。この処置にはいくつかの経緯上の理由がありますが、すべての最新のブラウザーで対応されており、実際に仕様書で定義されています。
例
この例では、この例では、 HTMLInputElement.files
プロパティで利用できるファイル情報を利用する、さらに高度なファイル選択ダイアログを示し、またいくつか巧妙なテクニックを示します。
メモ: この例の完全なソースコードは GitHub — file-example.html (ライブ版もあります) で見ることができます。 CSS については説明しません。 JavaScript が中心です。
最初に、 HTML を見てみましょう。
<form method="post" enctype="multipart/form-data">
<div>
<label for="image_uploads"
>アップロードする画像を選択してください (PNG, JPG)</label
>
<input
type="file"
id="image_uploads"
name="image_uploads"
accept=".jpg, .jpeg, .png"
multiple />
</div>
<div class="preview">
<p>アップロードするファイルが選択されていません</p>
</div>
<div>
<button>送信</button>
</div>
</form>
これは以前見たものに似ています。特筆するべきものはありません。
次に、 JavaScript を一通り見てみましょう。
スクリプトの最初の行で、フォームの入力欄自体と .preview
クラスが設定された <div>
要素の参照を取得します。次に <input>
要素を非表示にします。 — これは、ファイル入力欄が概して醜く、スタイル付けをするのが難しく、ブラウザー間でデザインに一貫性がないからです。 <label>
をクリックすることで input
要素をアクティブ化することができるので、 input
要素を見かけは非表示にしてラベルをボタンらしくしたほうが、ユーザーがファイルをアップロードしたいときの操作が分かります。
const input = document.querySelector("input");
const preview = document.querySelector(".preview");
input.style.opacity = 0;
メモ: ファイル入力欄を非表示にするために opacity
を使用し、 visibility: hidden
や display: none
を使用しないのは、支援技術が後二者のファイル入力欄が対話可能ではないと解釈するからです。
次に、イベントリスナーを入力欄に追加して、選択された値の変化 (この場合、ファイルが選択されたこと) を監視します。イベントリスナーは独自の updateImageDisplay()
関数を呼び出します。
input.addEventListener("change", updateImageDisplay);
updateImageDisplay()
関数が呼び出されるたびに、以下のことを行います。
-
while
ループを使ってプレビューの<div>
の中にある以前のコンテンツを空にします。 -
選択されたすべてのファイルの情報を持つ
FileList
オブジェクトを取り、curFiles
と呼ばれる変数に保存し����。 -
curFiles.length
が 0 かどうかをチェックすることで、ファイルが選択されていないかを確認します。選択されていない場合は、プレビューの<div>
に選択されているファイルがない旨のメッセージを表示します。 -
ファイルが選択されていた場合、ループで 1 つずつ、プレビューの
<div>
にそれについての情報を表示します。特筆するべきは次です。 -
独自の
validFileType()
関数を使用して、ファイルが正しい形式 (つまり、accept
属性で指定された画像形式) であるかどうかをチェックします。 -
そうであるなら、次のことを行います。
- ファイルの名前とファイルサイズを、前述の
<div>
(file.name
およびfile.size
で取得) 内のリストアイテムに出力します。独自のreturnFileSize()
関数はファイルサイズを バイト/KB/MB のうち適切な形式で返します (既定でブラウザーは長さを絶対的なバイトで返します)。 URL.createObjectURL(file)
を呼び出して、画像のプレビューのサムネイルを生成します。次に、新しい<img>
を生成し、そのsrc
をサムネイルに設定することで、リスト項目にも画像を挿入します。
- ファイルの名前とファイルサイズを、前述の
-
ファイル形式が無効である場合、リストのアイテム内にメッセージを表示して、ユーザーに別なファイル形式を選択する必要があることを伝えます。
function updateImageDisplay() {
while (preview.firstChild) {
preview.removeChild(preview.firstChild);
}
const curFiles = input.files;
if (curFiles.length === 0) {
const para = document.createElement("p");
para.textContent = "アップロードするファイルが選択されていません";
preview.appendChild(para);
} else {
const list = document.createElement("ol");
preview.appendChild(list);
for (const file of curFiles) {
const listItem = document.createElement("li");
const para = document.createElement("p");
if (validFileType(file)) {
para.textContent = `ファイル名: ${file.name}, ファイルサイズ: ${returnFileSize(
file.size,
)}.`;
const image = document.createElement("img");
image.src = URL.createObjectURL(file);
image.alt = image.title = file.name;
listItem.appendChild(image);
listItem.appendChild(para);
} else {
para.textContent = `ファイル名: ${file.name}: ファイル形式が有効ではありません。選択しなおしてください。`;
listItem.appendChild(para);
}
list.appendChild(listItem);
}
}
}
独自の validFileType()
関数は File
オブジェクトを引数として取り、それから Array.prototype.includes()
を使用して、 fileTypes
の中の値にファイルの type
プロパティに一致するものがあるかどうかをチェックします。一致するものが見つかった場合は、関数は true
を返します。一致するものが見つからなければ、 false
を返します。
// https://developer.mozilla.org/ja/docs/Web/Media/Formats/Image_types
const fileTypes = [
"image/apng",
"image/bmp",
"image/gif",
"image/jpeg",
"image/pjpeg",
"image/png",
"image/svg+xml",
"image/tiff",
"image/webp",
"image/x-icon",
];
function validFileType(file) {
return fileTypes.includes(file.type);
}
returnFileSize()
関数は数値(現在のファイルの size
プロパティから取得したバイト数)を取り、バイト/KB/MB のうち適切な形式で返します。
function returnFileSize(number) {
if (number < 1e3) {
return `${number} バイト`;
} else if (number >= 1e3 && number < 1e6) {
return `${(number / 1e3).toFixed(1)} KB`;
} else {
return `${(number / 1e6).toFixed(1)} MB`;
}
}
メモ: ここで使用されている "KB" および "MB" の単位は、1KB = 1000B という SI 接頭辞の慣例に従っており、macOS と同様です。システムが異なると、ファイルサイズの表し方も異なります。例えば、Ubuntu では 1KiB = 1024B という IEC 接頭辞を使用していますが、RAM の仕様では 2 のべき乗を表す SI 接頭辞 (1KB = 1024B) がよく使われます。このため、ここでは 1e3
(1000
) や 1e6
(100000
) を 1024
や 1048576
の代わりに使用しました。 アプリケーションでは、正確なサイズが重要である場合は、ユーザーに単位系を明確に伝える必要があります。
この例は次のようにできます。使ってみましょう。
技術的概要
仕様書
Specification |
---|
HTML Standard # file-upload-state-(type=file) |
ブラウザーの互換性
BCD tables only load in the browser
関連情報
- ウェブアプリケーションからのファイルの利用 —
<input type="file">
およびファイル API に関するたくさんの有用な例も含まれています。 - CSS プロパティの互換性