JavaScriptでファイルを読む
ファイルを選択し、ファイルのメタデータとコンテンツを読み取り、読み取りの進捗を監視する方法。
ユーザーのローカルデバイスにあるファイルを選択して操作することは、Webで最も一般的に使用される機能の1つです。これにより、ユーザーはファイルを選択し、サーバーにアップロードすることができます。たとえば、写真をアップロードしたり、税務書類の提出したりできます。ただし、サイトは、ネットワーク経由でデータを転送せずにファイルを読み取り、操作するということもできてしまいます。
最新の File System Access API #
File System Access API (ファイルシステムアクセス) API は、ユーザーのローカルシステム上のファイルとディレクトリの読み取りおよび書き込みの両方を簡単に行う方法を提供します。現在、ChromeやEdgeなど、ほとんどのChromium派生ブラウザで利用できます。詳細については、File System Access API の記事を参照してください。
File System Access API は、まだすべてのブラウザーと互換性があるわけではないため、利用可能な場合に新しいAPIを使用するヘルパーライブラリ、browser-fs-access、をご確認ください。新しいAPIが利用可能でない場合は、従来のアプローチにフォールバックします。
従来のやり方でファイルを操作する方法 #
このガイドでは、以下を行う方法について説明します。
ファイルを選択 #
HTML入力要素 #
ユーザーがファイルを選択できるようにする最も簡単な方法は、すべての主要なブラウザーでサポートされている<input type="file">
要素を使用することです。クリックすると、ユーザーはオペレーティングシステムの組み込みファイル選択UIを使用して、単一のファイル、またはmultiple
属性が含まれている場合は、複数のファイルを選択できます。ユーザーが1つまたは複数のファイルの選択を終了すると、要素のchange
イベントが発生します。ファイルの一覧は、FileList
オブジェクトであるevent.target.files
からアクセスできます。FileList
の各アイテムは、File
オブジェクトです。
<!-- The `multiple` attribute lets users select multiple files. -->
<input type="file" id="file-selector" multiple>
<script>
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
console.log(fileList);
});
</script>
この例では、ユーザーはオペレーティングシステムの組み込みファイル選択UIを使用して複数のファイルを選択し、選択した各ファイルをコンソールに記録できます。
ユーザーが選択できるファイルの種類を制限する #
場合によっては、ユーザーが選択できるファイルの種類を制限したいときがあります。たとえば、画像編集アプリが、テキストファイルではなく、画像のみを受け入れるようにする場合です。これを行うには、入力要素にaccept
属性を追加して、受け入れるファイルを指定します。
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">
カスタムドラッグアンドドロップ #
一部のブラウザでは、<input type="file">
要素もドロップターゲットであるため、ユーザーはアプリにファイルをドラッグアンドドロップできます。ただし、ドロップターゲットは小さいため、使いにくい場合があります。代わりに、<input type="file">
要素を使ってコア機能を指定したら、大きなカスタムドラッグアンドドロップサーフェスを提供できます。
ドロップゾーンを選択する #
ドロップサーフェスは、アプリケーションの設計によって異なります。ドロップサーフェスは、ウィンドウの一部のみ、またはウィンドウ全体にすることもできます。

Squooshを使用すると、ユーザーは画像をウィンドウ内の任意の場所にドラッグアンドドロップでき、画像を選択を選択すると、<input type="file">
要素が呼び出されます。何をドロップゾーンとする場合も、そのサーフェスにファイルをドラッグアンドドロップできることをユーザーが分かるようにしましょう。
ドロップゾーンを定義する #
要素をドラッグアンドドロップゾーンにするには、2 つのイベント dragover
と drop
をリッスンする必要があります。dragover
イベントは、ブラウザのUIを更新して、ドラッグアンドドロップアクションがファイルのコピーを作成していることを視覚的に示します。drop
イベントは、ユーザーがファイルをサーフェスにドロップした後に発生します。入力要素の場合と同じように、ファイルの一覧は、FileList
オブジェクトである event.dataTransfer.files
からアクセスできます。FileList
の各アイテムは、File
オブジェクトです。
const dropArea = document.getElementById('drop-area');
dropArea.addEventListener('dragover', (event) => {
event.stopPropagation();
event.preventDefault();
// Style the drag-and-drop as a "copy file" operation.
event.dataTransfer.dropEffect = 'copy';
});
dropArea.addEventListener('drop', (event) => {
event.stopPropagation();
event.preventDefault();
const fileList = event.dataTransfer.files;
console.log(fileList);
});
event.stopPropagation()
およびevent.preventDefault()
は、ブラウザーのデフォルトの動作が実行されないようにし、代わりにコードが実行されるようにします。これらのメソッドがないと、ブラウザはページから離れ、ユーザーがブラウザウィンドウにドロップしたファイルを開きます。
{#この例は埋め込みとしては機能しません。#}
ライブデモンストレーションは、Custom drag-and-drop (カスタムドラッグアンドドロップ)をご覧ください。
ディレクトリの場合は? #
残念ながら、現時点では、ディレクトリにアクセスする良い方法はありません。
<input type="file">
要素の webkitdirectory
属性を使用すると、単一のディレクトリまたは複数のディレクトリを選択できます。一部のChromiumベースのブラウザのほか、おそらくデスクトップ版のSafari でもサポートされていますが、ブラウザの互換性について矛盾した情報が報告されています。
ドラッグアンドドロップが有効になっていると、ユーザーはディレクトリをドロップゾーンにドラッグしようとするかもしれません。ドロップイベントが発生すると、ディレクトリの File
オブジェクトが含まれますが、ディレクトリ内のファイルには一切アクセスできなくなります。
ファイルメタデータの読み取り #
File
オブジェクトには、ファイルに関するいくつかのメタデータプロパティが含まれています。ほとんどのブラウザは、ファイル名、ファイルのサイズ、およびMIMEタイプを提供しますが、プラットフォームによっては、ブラウザが提供する情報が違ったり、他のブラウザよりも多くの情報が提供されたりする場合があります。
function getMetadataForFileList(fileList) {
for (const file of fileList) {
// Not supported in Safari for iOS.
const name = file.name ? file.name : 'NOT SUPPORTED';
// Not supported in Firefox for Android or Opera for Android.
const type = file.type ? file.type : 'NOT SUPPORTED';
// Unknown cross-browser support.
const size = file.size ? file.size : 'NOT SUPPORTED';
console.log({file, name, type, size});
}
}
実際の動作は、input-type-file
Glitch デモでご覧いただけます。
ファイルのコンテンツを読み取る #
ファイルを読み取るには、 FileReader
を使用します。これにより、File
オブジェクトのコンテンツをメモリに読み込むことができます。 FileReader
には、ファイルを配列バッファー、データURL 、またはテキストとして読み取るように指示できます。
function readImage(file) {
// Check if the file is an image.
if (file.type && !file.type.startsWith('image/')) {
console.log('File is not an image.', file.type, file);
return;
}
const reader = new FileReader();
reader.addEventListener('load', (event) => {
img.src = event.target.result;
});
reader.readAsDataURL(file);
}
上記の例では、ユーザーが指定した File
を読み取り、それをデータ URL に変換し、そのデータ URL を使って img
要素に画像を表示しています。ユーザーが画像ファイルを選択したことを確認する方法は、read-image-file
をご覧ください。
読み取られたファイルの進捗を監視する #
大きなファイルを読み取るときは、読み取りがどこまで進んだかを示すUXを提供すると便利な場合があります。そうするには、FileReader
が提供する progress
イベントを使用します。progress
イベントは、loaded
(読み取られた量) と total
(読み取る量の合計) という 2 つのプロパティを提供します。
function readFile(file) {
const reader = new FileReader();
reader.addEventListener('load', (event) => {
const result = event.target.result;
// Do something with result
});
reader.addEventListener('progress', (event) => {
if (event.loaded && event.total) {
const percent = (event.loaded / event.total) * 100;
console.log(`Progress: ${Math.round(percent)}`);
}
});
reader.readAsDataURL(file);
}
ヒーロー画像、Unsplash、Vincent Botta 氏提供