HTML5上のJavaScript（async/await, response）を利用したファイル出力/読み込み

# Introduction

Browser用JavaScriptによるファイルアップロード/ダウンロード方法を紹介．

サンプルファイルはJSONとする．

# Related Articles

1. [JavaScriptでJSONファイルダウンロード by Qiita](https://qiita.com/ganezasan/items/b5dbb42b966af0de44cb)

2. [Export JSON to CSV file using Javascript (in the browser)](https://medium.com/@danny.pule/export-json-to-csv-file-using-javascript-a0b7bc5b00d2)

3. [HTML5 FileReader how to return result?(using jQuery)](https://stackoverflow.com/questions/11829537/html5-filereader-how-to-return-result)

# Previous Methods

## Export

出力は`location.href`に`application/json`を仕込む．

```javascript
const items = JSON.stringfy('[:anyJSONItems]', null, '\t');
const blob = new Blob([items], { type: 'application/json' });

location.href = URL.createObjectURL(blob);
```

## Import

読み込みは`FileReader`を利用．

```javascript
function readFileModule(file, anyCallbackFunc) {
    const reader = new FileReader();

    reader.onload = e => {
      const result = e.target.result;
      const json = JSON.parse(result);
      anyCallbackFunc(json);
    };

    reader.readAsText(file);
};


const fileObj = document.querySelector("#select-file");

fileObj.addEventListener('change', async evt => {
    const file = evt.target.files[0];

    readFileModule(file, json => {
        console.log('# result json', json)
    });
},false);
```

# Proposal Methods

## Export

[Blob](https://developer.mozilla.org/ja/docs/Web/API/Blob)と`aタグ(<a></a>)`を利用する．

## Import

[async/await](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function)と[Response](https://developer.mozilla.org/ja/docs/Web/API/Response)を使う．

## sample code

```javascript:IO.js
const fileName = 'foo_bar.json'

export default {
  import: async file => {
    if (!file) return

    const response = await new Response(file)
    const jsonText = await response.text() // テキスト化
    return JSON.parse(jsonText)
  },
  export: items => {
    const jsonText = JSON.stringfy(items, null, '\t');
    const blob = new Blob([jsonText], { type: 'application/json;' })

    const _link = document.createElement('a') // aタグ作成
    if (_link !== undefined) {
      const url = URL.createObjectURL(blob)
      _link.setAttribute('href', url)
      _link.setAttribute('download', fileName) // ダウンロードさせるためには`download`属性が必須
      _link.style.visibility = 'hidden' // ブラウザ上には表示しない．
      document.body.appendChild(_link) // 一時的に`<body>`に追加
      _link.click() // aタグクリック
      document.body.removeChild(_link) // 削除
    }
  }
}
```

```javascript:app.js
import $IO from './IO.js'

// import
const fileObj = document.querySelector("#select-file");

fileObj.addEventListener('change', async evt => {
    console.log('# importing...')
    const file = evt.target.files[0];
    const json = await $IO.import(file)
    console.log('# result json', json)
    console.log('# imported!')
},false);

// export 
const exportBtn = document.querySelector("#export-btn");

exportBtn.addEventListener('click', async evt => {
    console.log('# exporting...')
    await $IO.export(items)
    console.log('# exported!')
}, false);
```

# References

1. [Using Promises with FileReader](https://blog.shovonhasan.com/using-promises-with-filereader/)

2. [Error using async and await with filereader](https://stackoverflow.com/questions/48172934/error-using-async-and-await-with-filereader)