HTML5 - File API

目次

File APIとは

File API とは、JavaScript からクライアント側のファイルにアクセスするための API です。下記で仕様が検討されています。

ただし、セキュリティを考慮して、アクセス可能なのは、利用者が意識的に選択、あるいはドラッグ&ドロップしたファイルのみに限られます。

現時点では下記のブラウザでサポートされています。

サンプル

File API のサンプルを下記に示します。ファイル選択部品で、UTF-8 で保存されたテキストファイルを指定すると、そのファイルの中身を表示します。

HTML
<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 属性を参照します。

HTML
<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 属性を参照します。

HTML
<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" とみなされます。

HTML
<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 属性に指定することで、画像を表示することができます。

HTML
<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() を使用することが推奨されています。

HTML
<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() などのビューオブジェクトを用いてアクセスします。

HTML
<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 バイトずつ読み込んでいます。

HTML
<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>