HTML5 - File API
- File APIとは
- サンプル
- インタフェース定義
- FileList オブジェクト
- Blob オブジェクト
- File オブジェクト
- FileReader オブジェクト
- ファイル取得
- ファイル読み込み
- ファイルのスライス読み込み
- リンク
File APIとは
File API とは、JavaScript からクライアント側のファイルにアクセスするための API です。下記で仕様が検討されています。
- 最新版: http://www.w3.org/TR/FileAPI/
- ワーキングドラフト: https://www.w3.org/TR/2017/WD-FileAPI-20171026/ [WD]
ただし、セキュリティを考慮して、アクセス可能なのは、利用者が意識的に選択、あるいはドラッグ&ドロップしたファイルのみに限られます。
現時点では下記のブラウザでサポートされています。
- Internet Explorer 10
- Firefox 3.6
- Google Chrome 6
- Safari 6
- Edge 12
- Opera 11.5
サンプル
File API のサンプルを下記に示します。ファイル選択部品で、UTF-8 で保存されたテキストファイルを指定すると、そのファイルの中身を表示します。
<div><input type="file" id="file1"></div> <div><output id="output1"></output></div> <script> window.addEventListener("load", function() { document.getElementById("file1").addEventListener("change", function() { var files = document.getElementById('file1').files; for (var i = 0; i < files.length; i++) { var file = files[i]; console.log("Name: " + file.name); console.log("Size: " + file.size); console.log("Type: " + file.type); console.log("Date: " + file.lastModified); console.log("Date: " + file.lastModifiedDate); var reader = new FileReader(); reader.onprogress = function(evt) { console.log("State: " + target.readyState); console.log("Loaded: " + evt.loaded); console.log("Total: " + evt.total); };; reader.onload = function(evt) { console.log("State: " + evt.target.readyState); console.log("Result: " + evt.target.result); document.getElementById("output1").innerHTML = evt.target.result; }; reader.onerror = function(evt) { console.log(evt.target.error.name); }; reader.readAsText(file, "utf-8"); } }); }); </script>
インタフェース定義
interface FileList { readonly attribute unsigned long length; getter File item(unsigned long index); }; interface Blob { readonly attribute unsigned long long size; readonly attribute DOMString type; Blob slice( optional long long start, optional long long end, optional DOMString contentType); }; interface File : Blob { readonly attribute DOMString name; readonly attribute long long lastModified; }; interface FileReader : EventTarget { readonly attribute unsigned short readyState; const unsigned short EMPTY = 0; const unsigned short LOADING = 1; const unsigned short DONE = 2; readonly attribute (DOMString or ArrayBuffer) result; readonly attribute DOMException error; void readAsArrayBuffer(Blob blob); void readAsBinaryString(Blob blob); void readAsText(Blob blob, optional DOMString encoding); void readAsDataURL(Blob blob); attribute EventHandler onloadstart; attribute EventHandler onprogress; attribute EventHandler onload; attribute EventHandler onabort; attribute EventHandler onerror; attribute EventHandler onloadend; };
FileList オブジェクト
FileList オブジェクトは下記のプロパティ、メソッドを持ちます。
プロパティ
- length
- ファイルオブジェクトの個数。
メソッド
- item(index)
- 0 から数えて index 番目ファイルオブジェクト。
Blob オブジェクト
Blob オブジェクトは下記のプロパティ、メソッドを持ちます。
プロパティ
- blob.size
- ファイルサイズ(バイト数単位)。
- blob.type
- text/plain, image/png などのファイル種別。
メソッド
- blob.slice(start, stop, contentType)
- ファイルを複数のスライスに分割して読み込む際に使用します。
File オブジェクト
File オブジェクトは、Blob が持つプロパティ、メソッドに加え、下記のプロパティを持ちます。
プロパティ
- file.name
- ファイル名。
- file.lastModified
- 最終更新日時。new Date(file.lastModified) で Date オブジェクトに変換可能。
FileReader オブジェクト
FileReader オブジェクトは、下記のプロパティ、メソッド、イベントハンドラを持ちます。
プロパティ
- reader.readyState
- 読み込み状態を示します。EMPTY(0), LODAING(1), DONE(2) いずれかの値を持ちます。
- reader.result
- 読み込み結果を保持します。読み込み形式(readAsXxxx) によって形式が異なります。
- reader.error
- エラーが発生した際の DOMExtension オブジェクトを保持します。
メソッド
- reader.readAsArrayBuffer(file)
- ファイルの内容を ArrayBuffer 形式で読み込みます。
- reader.readAsBinaryString(file)
- ファイルの内容をバイナリ形式で読み込みます。
- reader.readAsText(file, encoding)
- ファイルの内容をテキスト形式で読み込みます。encoding には "utf-8" などの文字コードを指定します。省略時は "utf-8" とみなされます。
- reader.readAsDataURL(file)
- ファイルの内容をデータURL形式で読み込みます。
- reader.abort()
- ファイルの読み込みを中断します。
イベントハンドラ
- reader.onloadstart
- 読み込みが開始した際に呼ばれます。
- reader.onprogress
- 途中経過の際に呼ばれます。FileReader オブジェクトの readyState 属性に状態が、total 属性に総バイト数、loaded 属性に読み込み済バイト数が設定されます。
- reader.onload
- 読み込みが完了した際に呼ばれます。FileReader オブジェクトの result 属性に、読み込みを行ったメソッドに応じた読み込み結果が格納されます。
- reader.onabort
- 読み込みが中断した際に呼ばれます。
- reader.onerror
- 読み込みがエラーとなった際に呼ばれます。FileReader オブジェクトの error 属性が DOMException オブジェクトを示し、その name 属性が "NotDoundError", "SecurityError", "NoReadableError" などのエラー種別を示します。
- reader.onloadend
- 読み込みが終了した際に呼ばれます。onload が成功した場合のみに呼び出されるのに対し、onloadend は成功・失敗に関わらず呼び出されます。
ファイル取得
読み込み可能なファイルを取得するには、2通りの方法があります。
- ファイル選択部品で選択する
- ファイルをドラッグ&ドロップする
ファイル選択部品で選択するには次のようにします。ファイル選択部品(<input type="file">) が変更された時点でハンドラが呼び出され、イベントターゲットであるファイル選択部品(e.target) の files 属性を参照します。
<div><input type="file" id="fileF1"></div> <div><output id="outputF1"></output></div> <script> window.addEventListener("load", function() { document.getElementById("fileF1").addEventListener("change", function(e) { var files = e.target.files; for (var i = 0; i < files.length; i++) { document.getElementById("outputF1").innerHTML += "<div>" + files[i].name + "</div>"; } }); }); </script>
ドラッグ&ドロップでファイルを取得するには次のようにします。イベントターゲットであるドロップ領域の dataTransfer.files 属性を参照します。
<div id="dropF2" style="height:50px; border: 1px solid gray;"> ここにファイルをドロップしてくさい </div> <div><output id="outputF2"></output></div> <script> window.addEventListener("load", function() { document.getElementById("dropF2").addEventListener("dragover", function(evt) { evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = "copy"; }); document.getElementById("dropF2").addEventListener("drop", function(evt) { evt.stopPropagation(); evt.preventDefault(); var files = evt.dataTransfer.files; for (var i = 0; i < files.length; i++) { document.getElementById("outputF2").innerHTML += "<div>" + files[i].name + "</div>"; } }); }); </script>
ファイル読み込み
ファイルを読み込み方として、下記の 4通りの方法がサポートされています。
- readAsText() : テキストとして読み込む
- readAsDataURL() : データURL形式で読み込む
- readAsBinaryString() : バイナリデータとして読み込む
- readAsArrayBuffer() : ArrayBuffer 形式で読み込む
readAsText(file, encoding) は、ファイルをテキストファイルとみなして読み込みます。encoding には、"utf-8", "Shift_JIS", "euc-jp", "iso-2022-jp" などの文字コードを指定します。省略時時は "utf-8" とみなされます。
<div><input type="file" id="fileR1"></div> <div><output id="outputR1"></output></div> <script> window.addEventListener("load", function() { document.getElementById("fileR1").addEventListener("change", function(e) { var files = e.target.files; for (var i = 0; i < files.length; i++) { var file = files[i]; var reader = new FileReader(); reader.onload = function(evt) { document.getElementById("outputR1").innerHTML = evt.target.result; }; reader.readAsText(file, "utf-8"); } }); }); </script>
readAsDataURL(file) は、URL の代わりに指定可能な形式で読み込みます。テキストの場合は data:text/plain;base64,77u/44GC44GE44GGDQo=、画像の場合は data:image/png;base64,iVBORw0... のような形式で読み込まれます。ここで得られた文字列を <img> の src 属性に指定することで、画像を表示することができます。
<div><input type="file" id="fileR2"></div> <div><output id="outputR2"></output></div> <script> window.addEventListener("load", function() { document.getElementById("fileR2").addEventListener("change", function(e) { var files = e.target.files; for (var i = 0; i < files.length; i++) { var file = files[i]; var reader = new FileReader(); reader.onload = function(evt) { document.getElementById("outputR2").innerHTML = evt.target.result; }; reader.readAsDataURL(file); } }); }); </script>
readAsBinaryString(file) は、ファイルをバイナリ形式で読み込みます。Internet Explorer 11 ではサポートされていません。現時点では、readAsBinaryString() は後方互換性のために残されており、代わりに readAsArrayBuffer() を使用することが推奨されています。
<div><input type="file" id="fileR3"></div> <div><output id="outputR3"></output></div> <script> window.addEventListener("load", function() { document.getElementById("fileR3").addEventListener("change", function(e) { var files = e.target.files; for (var i = 0; i < files.length; i++) { var file = files[i]; var reader = new FileReader(); reader.onload = function(evt) { document.getElementById("outputR3").innerHTML = window.btoa(evt.target.result); }; reader.readAsBinaryString(file); } }); }); </script>
readAsArrayBuffer(file) は、ファイルを ArrayBuffer 形式で読み込みます。ArrayBuffer は、Uint8Array(), Uint16Array(), Uint32Array(), Float64Array() などのビューオブジェクトを用いてアクセスします。
<div><input type="file" id="fileR4"></div> <div><output id="outputR4"></output></div> <script> window.addEventListener("load", function() { document.getElementById("fileR4").addEventListener("change", function(e) { var files = e.target.files; for (var i = 0; i < files.length; i++) { var file = files[i]; var reader = new FileReader(); reader.onload = function(evt) { var data = new Uint8Array(evt.target.result); for (var j = 0; j < data.length; j++) { document.getElementById("outputR4").innerHTML += (data[j] + " "); console.log(data[j]); } }; reader.readAsArrayBuffer(file); } }); }); </script>
ファイルのスライス読み込み
ファイルを複数のスライスに分割し、断片的に読み込むことで、巨大なファイルを複数の HTTP 通信に分割して送信することが可能となります。下記の例では、ファイルを 1024 バイトずつ読み込んでいます。
<div><input type="file" id="fileS1"></div> <script> var splitSize = 1024; window.addEventListener("load", function() { document.getElementById("fileS1").addEventListener("change", function(e) { var files = document.getElementById("fileS1").files; for (var i = 0; i < files.length; i++) { var file = files[i]; for (var j = 0; j < file.size; j += splitSize) { blob = file.slice(j, j + splitSize); var reader = new FileReader(blob); reader.onload = function (e) { // e.target.result を Ajux 等でサーバに送信する } reader.readAsBinaryString(blob); } } }); }); </script>