JavaScript　FileAPIについて学ぶ

#FileAPIとは？
ローカル（自分のパソコン内）にあるファイルを、JavaScriptを用いて操作することのできるAPI。例えば、自分のパソコンの中にある画像をブラウザ上(ChromeやSafariなど）に表示させたり、そのブラウザ上で画像を編集できたり、またそれをダウンロードしたりすることも可能。

#FileAPIの使用方法

##１HTMLでファイル選択ボタンを作成する
まず、以下のようなファイルを選択するためのボタンを用意する。
![スクリーンショット 2020-08-14 18.39.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421128/025aae91-3f06-f725-1de3-a46bf6355dfa.png)
そのためには、inputタグを用意し、typeを「file」に設定する。複数の画像を選択できるようにするには、追加で、「multiple」 属性を追加する。

```JavaScript
<!-- 画像を選択するボタン -->
<input id="input-file" type="file">

<!-- 複数画像を選択可能にする場合 -->
<input id="input-file" type="file" multiple>
```

##２JavaScriptで選択されたファイルの内容を確認してみる

試しに以下のようなコードを用意し、コンソールログで内容を確認してみる。

```javascript

// HTMLで作成したinput要素を、変数inputFileに代入
var inputFile = document.getElementById('input-file');

// そのinputファイルに変化が生じた（画像が選択された）とき、
// ファイルの情報をコンソール上に出力せよ
inputFile.addEventListener("change", function(e) {
 console.log(e.target.files)
},false);
```
＊**「e.target.files」には選択されたファイルの内容などが格納されている。**
![スクリーンショット 2020-08-15 17.19.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421128/e98bee1b-1978-89e3-518e-9c9877784781.png)
まず一番上に**FileListオブジェクト**がある。これには選択されたファイルの数が格納される「length」プロパティがある。
そのFileListオブジェクトの子オブジェクトとして、**Fileオブジェクト**が存在する。そこには下にあげたような複数のプロパティがセットされてある。このプロパティを使用するだけで、「画像サイズを100kb以下の画像しかアップできない」「画像しかアップロードできない」といったバリデーションをかけることができる。

|プロパティ名|内容|
|:---|:---
|lastModifiedDate|ファイルの最終更新日|
|name|ファイル名|
|size|ファイルサイズ|
|type|ファイルのタイプ・拡張子|

##３読み込んだファイルを出力してみる

ここでは**FileReaderクラス**を使用する。このクラスは、対象のファイルの内容を読み取ることができる。このクラスには以下のプロパティとメソッドがあらかじめセットされている。（そんなのがあるんだ〜程度でよい）

|プロパティ名|内容|
|:---|:---
|readyState|現在の読み取り状態を取得する|
|result|読み取り成功後、読み取ったデータを取得する|
|error|読み取り失敗後、エラーオブジェクトを取得する|

|メソッド名|内容|
|:---|:---
|readAsArrayBuffer|ファイルをArrayBuferをして読み込む|
|readAsText|ファイルの中身をテキストとして読み込む|
|readAsDataURL|画像ファイルの場所をURLとして読み込む|

FileReaderクラスに内容を確認できたところで、実際にこれを使用し、ファイルをブラウザ上に出力してみる。

###3-1 FileReaderクラスをインスタンス化する

```JavaScript
var reader = new FileReader()
```
FileReaderクラスのままでは、上に書いたプロパティやメソッドを使用することができないので、以下のようにまずはインスタンス化しておく。
###3-2 FileReaderクラスのメソッドを使用しファイルのローカルURLを取得する

```JavaScript
reader.readAsDataURL(file[0])
```
・上で示したメソッドのうち、**readAsDataURLメソッド**を使用し、自分のパソコン上におけるファイルのURLを取得する。
・引数の「file」はURLを取得するためのファイルを指定する。
・「0」はファイルオブジェクトの一番最初のファイルを指す。上で見たようにファイル内容は配列の形で格納されているため。
・**取得したローカルURLは、読み取り結果としてreaderインスタンスの「resultプロパティ」に格納される。**


###3-3　取得したローカルURLをimgタグのSRC属性に代入

```JavaScript
reader.onload = function() {
 image.src = reader.result
)
```
・「onload」とは、ページや画像ファイルなどのすべてのリソースを読み込んでから、何らかの処理をするときに使用するイベントハンドラー。ここでは、function()以下が、読み込み終了後に行う処理である。
・上で書いたように指定したファイルのローカルURLはreaderインスタンスの「result」プロパティに格納されているため、それをimgタグのsrc 属性に代入すれば、ブラウザ上でローカルな画像も表示することが可能になる。

##４　まとめ（ブラウザ上にローカルファイルを表示させるまでの流れ）

**index.html**

```html
<body>
   <input type="file" id="input-file" /> <!--単一のファイルを読み込む場合-->
   <img id="image" />
   <script src="./qiita.js" ></script>
 </body>
```

**qiita.js**

```JavaScript
// ファイルを選択するためのinput要素と、選択したファイルのURLを差し込むためのimg要素をそれぞれ取得
var inputfile = document.getElementById('inputfile')
var image = document.getElementById('image')
 
// input要素に変化が起きたとき（ファイルが選択されたとき）、以下の処理を実行させる
inputfile.addEventListener("change", function(e) {
 
  // 選択されたファイルの内容を代入
  var file = e.target.files 

  // FileReaderクラスをインスタンス化し、ファイル出力の準備をする
  var reader = new FileReader()

  // ファイルオブジェクトの一番最初のファイルのローカルURLを読み取り、それをreaderインスタンスのresultプロパティにセット
  reader.readAsDataURL(file[0])

  //読み取り終了後、読み取ったローカルURLをimgタグのsrc属性に代入する。
  reader.onload = function() {
    image.src = reader.result;
  }
}, false)
```

以上により、ブラウザ上に自分のローカルな画像を表示させることができた。これは、よくアプリのプロフィール画像の設定にある「プレビュー機能」として応用できる。

##参考
[JavaScriptでFile APIを用いたファイル操作方法ついて解説](https://www.e-loop.jp/knowledges/35/#:~:text=File%20API%E3%81%A8%E3%81%AF%E8%87%AA%E8%BA%AB,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)