File API とは、JavaScript からクライアント側のファイルにアクセスするための API です。下記で仕様が検討されています。
ただし、セキュリティを考慮して、アクセス可能なのは、利用者が意識的に選択、あるいはドラッグ&ドロップしたファイルのみに限られます。
現時点では下記のブラウザでサポートされています。
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 オブジェクトは下記のプロパティ、メソッドを持ちます。
Blob オブジェクトは下記のプロパティ、メソッドを持ちます。
File オブジェクトは、Blob が持つプロパティ、メソッドに加え、下記のプロパティを持ちます。
FileReader オブジェクトは、下記のプロパティ、メソッド、イベントハンドラを持ちます。
読み込み可能なファイルを取得するには、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(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>