FileReader は「ファイルの中身を“いろんな形”で読み出すための専用リーダー」
前回の File API で出てきた File は、
「ユーザーが選んだファイルへのハンドル(取っ手)」でした。
でも、File だけでは中身は読めません。
「このファイルの中身を文字列で欲しい」「画像として表示したい」など、
具体的な形に変換してくれる存在が必要です。
その役割を担うのが FileReader です。
FileReader はざっくり言うと、
ファイル(File / Blob)の中身を
文字列として読む(readAsText)
画像などに使える data URL として読む(readAsDataURL)
バイナリとして読む(readAsArrayBuffer)
ための「非同期リーダー」です。
「非同期」というのがとても重要で、
読み込みが終わったタイミングでイベント(load など)が発火し、
そのときに reader.result に中身が入ります。
基本の流れ:「File を受け取る → FileReader で読む」
HTML でファイルを選ばせる
まずは、ユーザーにファイルを選んでもらいます。
<input type="file" id="fileInput">
<pre id="output"></pre>
JavaScript で FileReader を使う基本形
const input = document.querySelector("#fileInput");
const output = document.querySelector("#output");
input.addEventListener("change", () => {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
reader.addEventListener("load", () => {
// 読み込み完了時、result に中身が入っている
output.textContent = reader.result;
});
reader.addEventListener("error", () => {
console.error("読み込みに失敗しました:", reader.error);
});
reader.readAsText(file, "utf-8");
});
JavaScriptここで押さえてほしい重要ポイントは 2 つです。
1つ目は、読み込みは非同期 だということ。readAsText を呼んだ瞬間にはまだ結果はありません。
読み込みが終わったときに load イベントが発火し、
そのタイミングで reader.result を使います。
2つ目は、読み方をメソッドで選ぶ ということ。readAsText なのか readAsDataURL なのかで、result の中身の「型」が変わります。
readAsText:テキストファイルを文字列として読む
テキスト読み込みの典型パターン
テキストファイル(.txt, .csv, .json など)を読みたいときは、readAsText を使います。
const reader = new FileReader();
reader.addEventListener("load", () => {
const text = reader.result; // string
console.log("中身:", text);
});
reader.readAsText(file, "utf-8");
JavaScript第2引数で文字コードを指定できます。
日本語環境だと、"utf-8" を指定しておくのが無難です。
例題:テキストファイルを読み込んで行ごとに表示する
HTML:
<input type="file" id="fileInput" accept=".txt">
<pre id="output"></pre>
JavaScript:
const input = document.querySelector("#fileInput");
const output = document.querySelector("#output");
input.addEventListener("change", () => {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
reader.addEventListener("load", () => {
const text = reader.result;
const lines = text.split("\n");
output.textContent = lines.map((line, i) => `${i + 1}: ${line}`).join("\n");
});
reader.readAsText(file, "utf-8");
});
JavaScriptここでの流れは、
File を受け取る
FileReader で readAsText するload イベントで result を文字列として受け取るsplit("\n") で行ごとに分割して表示する
という、とても素直なものです。
「FileReader は、File を“ただの文字列”に変えてくれる」と思うと、
一気にイメージしやすくなります。
readAsDataURL:画像プレビューの定番パターン
data URL とは何か
readAsDataURL を使うと、
ファイルの中身を data URL という形式の文字列に変換してくれます。
例えば画像なら、data:image/png;base64,.... のような長い文字列です。
この文字列を <img> の src に入れると、
そのまま画像として表示できます。
画像プレビューのコード
HTML:
<input type="file" id="fileInput" accept="image/*">
<img id="preview" alt="プレビュー" style="max-width: 200px;">
JavaScript:
const input = document.querySelector("#fileInput");
const img = document.querySelector("#preview");
input.addEventListener("change", () => {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
reader.addEventListener("load", () => {
img.src = reader.result; // data URL が入る
});
reader.readAsDataURL(file);
});
JavaScriptここでの重要ポイントは、
FileReader が「ファイル → data URL 文字列」に変換してくれる
その文字列を img.src に入れるだけでプレビューできる
というシンプルさです。
「アップロード前に画像を確認させたい」という要件では、
このパターンがほぼ定番になっています。
readAsArrayBuffer:バイナリとして扱いたいとき
バイナリデータをそのまま扱う
画像や音声、PDF などを
「自分でバイナリとして処理したい」場合は、readAsArrayBuffer を使います。
const reader = new FileReader();
reader.addEventListener("load", () => {
const buffer = reader.result; // ArrayBuffer
console.log(buffer.byteLength);
});
reader.readAsArrayBuffer(file);
JavaScriptArrayBuffer は「生のバイト列」を表すオブジェクトで、
TypedArray(Uint8Array など)と組み合わせて使います。
初心者のうちは、
「バイナリをガチで触るときに使うモード」くらいの理解で十分です。
テキストや画像プレビューが目的なら、readAsText と readAsDataURL だけでかなりのことができます。
FileReader が「イベント駆動」であることをしっかり理解する
なぜ同期ではなく非同期なのか
ファイル読み込みは、
サイズが大きくなると時間がかかります。
もし同期的(const result = reader.readAsText(file) みたいな形)だったら、
読み込みが終わるまでブラウザ全体が固まってしまいます。
それを避けるために、FileReader は 非同期+イベント という形になっています。
readAsText や readAsDataURL を呼ぶ
読み込みがバックグラウンドで進む
終わったら load イベントが発火
そのときに reader.result を使う
という流れです。
よく使うイベント
最低限覚えておきたいのはこの 2 つです。
load
読み込みが正常に完了したとき
error
読み込み中にエラーが起きたとき
例えば、こんな書き方がよく使われます。
const reader = new FileReader();
reader.addEventListener("load", () => {
console.log("成功:", reader.result);
});
reader.addEventListener("error", () => {
console.error("失敗:", reader.error);
});
reader.readAsText(file, "utf-8");
JavaScript大きなファイルで進捗バーを出したいときは、progress イベントも使えますが、
最初のうちは load と error だけで十分です。
例題:FileReader を Promise 化して async/await で使う(少し応用)
イベントリスナーで書くと、
ネストが増えて読みにくくなることがあります。
そこで、FileReader を Promise で包んでしまうテクニックがあります。
function readFileAsText(file, encoding = "utf-8") {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener("load", () => {
resolve(reader.result);
});
reader.addEventListener("error", () => {
reject(reader.error);
});
reader.readAsText(file, encoding);
});
}
JavaScriptこれを使うと、こう書けます。
input.addEventListener("change", async () => {
const file = input.files[0];
if (!file) return;
try {
const text = await readFileAsText(file);
console.log("中身:", text);
} catch (err) {
console.error("読み込み失敗:", err);
}
});
JavaScript「イベント駆動」を「async/await の世界」に持ち込むことで、
処理の流れが頭に入りやすくなります。
これは少し応用寄りですが、
FileReader の非同期性をより深く理解するのに役立ちます。
初心者として FileReader で本当に掴んでほしいこと
FileReader は「File / Blob の中身を読み込むためのリーダー」
読み込みは必ず非同期で、readAsText などを呼んだあとに load イベントで結果を受け取るreadAsText はテキスト用、readAsDataURL は画像プレビューなどに便利、readAsArrayBuffer はバイナリ処理用
結果は常に reader.result に入るが、そのタイミングは「load が発火したとき」
FileReader は「ユーザーが選んだファイル」に対してだけ使える(勝手にローカルを読むことはできない)
まずは次の 2 つを、自分の手で書いてみてください。
テキストファイルを選んで中身を <pre> に表示する(readAsText)
画像ファイルを選んで <img> にプレビュー表示する(readAsDataURL)
この 2 つがスムーズに書けるようになったとき、
FileReader は単なる API ではなく、
「ローカルのファイルと Web アプリをつなぐための、頼れる読書係」に見えてくるはずです。
