JavaScript | Web API:ファイル・データ操作 - input type=”file”

JavaScript JavaScript
スポンサーリンク

input type=”file” は「ユーザーにファイルを選んでもらうための唯一の正規ルート」

まず大前提として、
ブラウザの JavaScript は、勝手にユーザーのパソコンの中を覗けません。

「このファイルをブラウザに渡してもいいよ」と
ユーザーが自分の手で選んだときだけ、そのファイルに触れます。

その“入口”になるのが <input type="file"> です。

この要素があるからこそ、

  • 画像をアップロード
  • CSV を読み込んで処理
  • PDF をサーバーに送信
  • ローカルのテキストを読み込んで表示

といったことが、安全に実現できます。


基本の形:input type=”file” と change イベント

HTML と JavaScript の最小構成

HTML:

<input type="file" id="fileInput">

JavaScript:

const input = document.querySelector("#fileInput");

input.addEventListener("change", () => {
  const files = input.files; // FileList
  console.log(files);
});
JavaScript

ここで重要なのは 2 つです。

1つ目は、change イベントが「ユーザーがファイル選択ダイアログで決定したタイミング」で発火すること。
2つ目は、input.filesFileList(ファイルの配列のようなもの) が入ること。

FileList の中身は File オブジェクトです。

const file = input.files[0];
console.log(file.name); // ファイル名
console.log(file.size); // バイト数
console.log(file.type); // MIME タイプ(image/png など)
JavaScript

ここまでが「ファイルを選んでもらう」部分。
この先は File API / FileReader / Blob の世界につながっていきます。


accept 属性で「選んでほしいファイルの種類」をヒントに出す

画像だけ選ばせたい場合

HTML:

<input type="file" id="imageInput" accept="image/*">

accept="image/*" と書くと、
ファイル選択ダイアログで「画像ファイル」が優先的に表示されます。

他にも、

<input type="file" accept=".txt">
<input type="file" accept=".csv,.tsv">
<input type="file" accept="application/pdf">

のように、拡張子や MIME タイプで指定できます。

ここでのポイントは、

  • accept は「ユーザーへのヒント」であって、完全な制限ではない
  • JavaScript 側でも file.typefile.name をチェックしておくと安心

ということです。

例えば、画像だけ受け付けたいなら、
こういうチェックを入れます。

const file = input.files[0];
if (!file.type.startsWith("image/")) {
  alert("画像ファイルを選んでください");
  return;
}
JavaScript

multiple 属性で「複数ファイル」を選べるようにする

HTML 側で multiple を付ける

<input type="file" id="multiInput" multiple>

これで、ユーザーは一度に複数のファイルを選べます。

JavaScript 側では、input.files に複数の File が入ります。

const input = document.querySelector("#multiInput");

input.addEventListener("change", () => {
  const files = input.files;

  Array.from(files).forEach((file) => {
    console.log(file.name, file.size);
  });
});
JavaScript

ここで押さえておきたいのは、

  • files は配列ではなく FileList(配列風)なので、Array.from で配列にすると扱いやすい
  • 複数ファイルアップロードや一括処理の入口になる

という点です。


例題①:選んだ画像ファイルをプレビュー表示する

HTML

<input type="file" id="imageInput" accept="image/*">
<img id="preview" alt="プレビュー" style="max-width: 200px; display: block; margin-top: 8px;">

JavaScript(URL.createObjectURL を使うパターン)

const input = document.querySelector("#imageInput");
const preview = document.querySelector("#preview");

input.addEventListener("change", () => {
  const file = input.files[0];
  if (!file) return;

  if (!file.type.startsWith("image/")) {
    alert("画像ファイルを選んでください");
    return;
  }

  const url = URL.createObjectURL(file);
  preview.src = url;
});
JavaScript

流れを整理すると、

ユーザーが画像ファイルを選ぶ
input.files[0] から File を受け取る
file.type で画像かどうか軽くチェック
URL.createObjectURL(file) で一時 URL を作る
その URL を img.src にセットしてプレビュー

という構成です。

ここで掴んでほしいのは、

「input type=”file” は File を渡してくれるだけ」
「それをどう扱うかは JavaScript 次第」

という感覚です。


例題②:選んだテキストファイルの中身を画面に表示する

HTML

<input type="file" id="textInput" accept=".txt">
<pre id="output"></pre>

JavaScript(FileReader を使う)

const input = document.querySelector("#textInput");
const output = document.querySelector("#output");

input.addEventListener("change", () => {
  const file = input.files[0];
  if (!file) return;

  const reader = new FileReader();

  reader.addEventListener("load", () => {
    output.textContent = reader.result;
  });

  reader.addEventListener("error", () => {
    console.error("読み込みに失敗しました:", reader.error);
  });

  reader.readAsText(file, "utf-8");
});
JavaScript

ここでの流れは、

input type=”file” で File を受け取る
FileReader で readAsText する
load イベントで reader.result に中身の文字列が入る
それを <pre> に表示する

というものです。

「ファイル選択 → File → FileReader → 表示」という一連の流れが
体に入ると、ファイル操作の基礎はほぼクリアです。


重要ポイント:セキュリティと制約をちゃんと理解する

JavaScript は「好きなファイル」を勝手に読めない

<input type="file"> がないと、
JavaScript はユーザーのローカルファイルに一切アクセスできません。

そして、input があっても、

  • ユーザーが自分で選んだファイルだけ
  • 選んだファイルのパス(C:… など)は基本的に分からない
  • そのファイルを勝手に保存し直したり、上書きしたりはできない

という制約があります。

これは、ユーザーのプライバシーと安全のために
ブラウザが絶対に守っているルールです。

開発者としては、

「ユーザーが選んだファイルを一時的に読み、
必要ならサーバーに送る or ブラウザ内で処理する」

という前提で設計する必要があります。

value を直接書き換えても意味はない

<input type="text"> なら input.value = "abc" で値を変えられますが、
<input type="file">value は特別扱いです。

セキュリティ上の理由から、
JavaScript から任意のファイルパスを value にセットすることはできません。

つまり、

fileInput.value = "C:\\secret.txt"; // こんなことはできない
JavaScript

ということです。

「ファイルを選ぶ」のは、
必ずユーザーの操作でなければいけない、というルールがあると覚えておいてください。


重要ポイント:UI としての input type=”file” をどう扱うか

見た目をカスタマイズしたい場合

<input type="file"> はブラウザ標準の見た目なので、
そのままだとデザイン的に浮くことがあります。

よくやるパターンは、

  • input を画面から隠す(display: none など)
  • 代わりにボタンやラベルを表示する
  • そのボタンをクリックしたときに input.click() を呼ぶ

というものです。

HTML:

<input type="file" id="fileInput" style="display:none;">
<button id="selectBtn">ファイルを選択</button>
<span id="fileName">未選択</span>

JavaScript:

const input = document.querySelector("#fileInput");
const btn = document.querySelector("#selectBtn");
const fileName = document.querySelector("#fileName");

btn.addEventListener("click", () => {
  input.click(); // 本物の input をクリックさせる
});

input.addEventListener("change", () => {
  const file = input.files[0];
  fileName.textContent = file ? file.name : "未選択";
});
JavaScript

こうすると、

見た目は自分好みのボタン
実際のファイル選択は隠れた input が担当

という構成になります。


例題③:input type=”file” とドラッグ&ドロップを両方サポートする

実務では、

「クリックして選択」も「ドラッグ&ドロップ」も
両方使える UI がよくあります。

HTML:

<input type="file" id="fileInput" multiple style="display:none;">
<div id="dropzone" style="width:300px;height:150px;border:2px dashed #666;display:flex;align-items:center;justify-content:center;margin-bottom:8px;cursor:pointer;">
  クリックまたはファイルをドロップ
</div>
<ul id="fileList"></ul>

JavaScript(ざっくり):

const input = document.querySelector("#fileInput");
const dropzone = document.querySelector("#dropzone");
const fileList = document.querySelector("#fileList");

function handleFiles(files) {
  fileList.innerHTML = "";
  Array.from(files).forEach(file => {
    const li = document.createElement("li");
    li.textContent = `${file.name} (${file.size} bytes)`;
    fileList.appendChild(li);
  });
}

dropzone.addEventListener("click", () => {
  input.click();
});

input.addEventListener("change", () => {
  handleFiles(input.files);
});

dropzone.addEventListener("dragover", (event) => {
  event.preventDefault();
  dropzone.style.backgroundColor = "#eef";
});

dropzone.addEventListener("dragleave", () => {
  dropzone.style.backgroundColor = "";
});

dropzone.addEventListener("drop", (event) => {
  event.preventDefault();
  dropzone.style.backgroundColor = "";
  handleFiles(event.dataTransfer.files);
});
JavaScript

ここでのポイントは、

  • ファイルの処理ロジックを handleFiles にまとめている
  • input から来ても、ドラッグ&ドロップから来ても、同じ処理を使い回せる

というところです。

input type="file" は「クリックで選ぶ」入口、
ドラッグ&ドロップは「マウスで放り込む」入口、
どちらも最終的には FileList に収束します。


初心者として input type=”file” で本当に掴んでほしいこと

<input type="file"> は「ユーザーにファイルを選んでもらうための唯一の正規ルート」
change イベントで input.files(FileList)を受け取る
accept で「選んでほしい種類」をヒントとして出せる
multiple で複数ファイル選択ができる
JavaScript から任意のファイルパスをセットすることはできない(セキュリティ上の制約)
見た目は隠して、ボタン+input.click() でカスタム UI にするのが定番

まずは次の 2 つを、自分の手で書いてみてください。

  • テキストファイルを選んで中身を <pre> に表示する
  • 画像ファイルを選んで <img> にプレビュー表示する

これがスムーズに書けるようになったとき、
input type="file" は単なるフォーム部品ではなく、
「ユーザーのローカルデータと、あなたの Web アプリをつなぐ入り口」
として、かなり頼もしく感じられるはずです。

タイトルとURLをコピーしました