JavaScriptでファイルのインポート、エクスポートを実装する

Chrome/Firefoxの拡張機能で、設定をインポート、エクスポートする機能が欲しいといった要望があったので、まずはどんな感じにインポート、エクスポートすれば良いんだっけ、、ってことでJavaScriptで簡単なサンプル書いてみました。

コード

下記のようなHTMLを用意します。インポート、エクスポート用のボタンがあって、インポートしたものを表示するエリアを用意しておきます。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <button type="button" id="inputFile">Import</button>
    <pre><code id="contents"></code></pre>
    <button type="button" id="outputFile">Export</button>
    <script src="file.js"></script>
  </body>
</html>

JavaScriptは下記のような感じで。

let currentContents = '';
const displayElement = document.getElementById('contents');

document.getElementById('inputFile').addEventListener('click', (e) => {
  const fileInput = document.createElement('input');
  fileInput.type = 'file';
  fileInput.setAttribute('hidden', true);

  fileInput.addEventListener('change', (e) => {
    const file = e.target.files[0];
  
    const reader = new FileReader();
    reader.onload = (e) => {
      const fileContents = e.target.result;
      displayElement.textContent = fileContents;
      currentContents = fileContents;
    }
    reader.readAsText(file);
  }, false);
  
  document.body.appendChild(fileInput);
  fileInput.click();
  fileInput.remove();
}, false);


document.getElementById('outputFile').addEventListener('click', (e) => {
  const downloadLink = document.createElement('a');
  downloadLink.download = 'export.txt';
  downloadLink.href = URL.createObjectURL(new Blob([currentContents], { 'type' : 'text/plain' }));
  downloadLink.setAttribute('hidden', true);

  document.body.appendChild(downloadLink);
  downloadLink.click();
  downloadLink.remove();
}, false);

インポートのボタンが押下された際に、ファイル選択用のinput要素を生成してclickを呼び出してファイル選択ダイアログを表示させます。
ファイルが選択されたら、それをFileReaderを使って読みだして表示します。

エクスポートのボタンが押下されたら、BlobからURLを生成し、それをリンクとしてa要素を生成してclickといった流れでダウンロードさせています。

Firefoxだとbody配下に入れないとclickが効かないので、body.appendChildしてremoveといったことをやっています。

動作

とりあえずFirefox、Chrome、Edgeの最新バージョンで動作することを確認済みです。

f:id:onozaty:20191014010546g:plain