ファイルを同期・非同期で読み込む[FileReaderSync/FileReader]
JavaScriptでファイルを「同期、非同期」で読む込む方法です。同期はスクリプトの実行と共に連続してファイルを読み込みます。非同期はスクリプトの実行とは別で一連のイベントが完了後にファイルを読み込みます。
※この記事の同期とは「連続してファイルを読み込む事」を同期としています。
非同期でファイルを読み込む
非同期でファイルを読み込むには「FileReader」オブジェクトを使用します。FileReader.readAsArrayBuffer()でファイルを読み込み、読み込みが成功した場合にFileReader.onload()のイベントが発生します。
<html> <head> <meta charset="UTF-8"> <script type="text/javascript"> window.onload = function(){ var obj = document.getElementById("inputfile"); obj.addEventListener("change",onAddFile,false); } // ユーザーによりファイルが追加された function onAddFile(event) { var file = event.target.files; var reader = new FileReader(); reader.onload = function (ev) { // ファイルの中身を取得 var Stream = new Uint8Array(reader.result); // ... (ここに処理を追加する) // ファイルサイズを表示 alert(Stream.length + 'バイト'); }; reader.readAsArrayBuffer(file[0]); } </script> </head> <body> <form> <input type="file" id="inputfile"> </form> </body> </html>
ファイルを読み込んで、ファイルサイズをアラートで表示しています。
連続してファイルを読み込む(同期もどき)
連続してファイルを読み込むには「FileReaderSync」オブジェクトを使用します。このFileReaderSyncオブジェクトはWorkerオブジェクトで実行する必要があります。また、Workerオブジェクトは基本的に別ファイルで定義します。
[fileworkers.js]
// ファイルを読み込む onmessage = function (event) { var reader = new FileReaderSync(); var raw = reader.readAsArrayBuffer(event.data.file); postMessage({"raw": raw, "name": event.data.file.name }); };
[HTML]
<html> <head> <meta charset="UTF-8"> <script type="text/javascript"> var worker = new Worker('fileworkers.js'); window.onload = function(){ var obj = document.getElementById("inputfile"); obj.addEventListener("change",onAddFile,false); } // ユーザーによりファイルが追加された function onAddFile(event) { var files = event.target.files; document.getElementById("lst_file").innerHTML = ''; // ワーカー経由でファイルを読み込む for (var i = 0; i < files.length; i++) { worker.postMessage({ "file": files[i]}); } } // Workerからのメッセージ worker.onmessage = function (event) { // ファイルの中身を取得 //var Stream = new Uint8Array(event.data.raw); // ... (ここに処理を追加する) // ファイル名をリストに表示する document.getElementById("lst_file").innerHTML = document.getElementById("lst_file").innerHTML + event.data.name + '\n'; } </script> </head> <body> <form> <input type="file" id="inputfile" multiple><br> <textarea id="lst_file" rows="10" cols="40" style="width:576px;" readonly></textarea> </form> </body> </html>
このサンプルでは複数のファイルを連続して読み取ってファイル名を出力しています。実際はUint8Arrayのバイナリ配列から内容を読み取る処理を適宜、追加します。
Chromeの注意事項
ご使用のブラウザがChromeの場合はローカルで実行すると「Workerオブジェクト」のセキュリティエラーが発生します。
このエラーはChromeのセキュリティ対策の仕様です。尚、Webサーバー経由で実行するとエラーは出ません。
ローカル環境でエラーを表示させないようにするには「Web Workerに画像データを値渡しではなく参照渡しする」の事前準備をご覧ください。
対応ブラウザ
IE11/EdgeとChrome、FireFoxで確認しました。