ステップ 6: Todo をファイル システムにエクスポートする

このステップでは、次のことを学習します。

  • 外部ファイルシステム内のファイルへの参照を取得する方法。
  • ファイル システムへの書き込み方法。

このステップの推定所要時間は 20 分です。
このページの一番下に移動 ↓ すると、この手順を完了できます。

ToDo リストをエクスポート

このステップでは、アプリにエクスポート ボタンを追加します。このボタンをクリックすると、ユーザーが選択したテキスト ファイルに現在の ToDo アイテムが保存されます。ファイルが存在する場合は置き換えられます。それ以外の場合は、新しいファイルが作成されます。

許可を更新

ファイル システムの権限は、読み取り専用アクセスの文字列、または追加のプロパティを持つオブジェクトとしてリクエストできます。例:

// Read only
"permissions": ["fileSystem"]

// Read and write
"permissions": [{"fileSystem": ["write"]}]

// Read, write, autocomplate previous input, and select folder directories instead of files
"permissions": [{"fileSystem": ["write", "retainEntries", "directory"]}]

読み取りと書き込みのアクセス権が必要です。manifest.json で、{fileSystem: [ "write" ] } 権限をリクエストします。

"permissions": [
  "storage", 
  "alarms", 
  "notifications", 
  "webview",
  "<all_urls>", 
  { "fileSystem": ["write"] } 
],

HTML ビューの更新

index.html に [ディスクにエクスポート] ボタンと、アプリにステータス メッセージを表示する div を追加します。

<footer id="info">
  <button id="toggleAlarm">Activate alarm</button>
  <button id="exportToDisk">Export to disk</button>
  <div id="status"></div>
  ...
</footer>

また、index.htmlexport.js スクリプトを読み込みます。

...
<script src="js/alarms.js"></script>
<script src="js/export.js"></script>

エクスポート スクリプトを作成する

以下のコードを使用して、export.js という名前の新しい JavaScript ファイルを作成します。これを js フォルダに保存します。

(function() {

  var dbName = 'todos-vanillajs';

  var savedFileEntry, fileDisplayPath;

  function getTodosAsText(callback) {
  }

  function exportToFileEntry(fileEntry) {
  }

  function doExportToDisk() {
  }

  document.getElementById('exportToDisk').addEventListener('click', doExportToDisk);

})();

現在、export.js には、[ディスクにエクスポート] ボタンのクリック リスナーと、getTodosAsText()exportToFileEntrydoExportToDisk() のスタブのみが含まれています。

ToDo アイテムをテキストとして取得する

getTodosAsText() を更新して、chrome.storage.local から Todo を読み取り、それらのテキスト表現を生成するようにします。

function getTodosAsText(callback) {
  chrome.storage.local.get(dbName, function(storedData) {
    var text = '';

    if ( storedData[dbName].todos ) {
      storedData[dbName].todos.forEach(function(todo) {
          text += '- ';
          if ( todo.completed ) {
            text += '[DONE] ';
          }
          text += todo.title;
          text += '\n';
        }, '');
    }

    callback(text);

  }.bind(this));
}

ファイルを選択

doExportToDisk()chrome.fileSystem.chooseEntry() で更新して、ユーザーがファイルを選択できるようにします。

function doExportToDisk() {

  if (savedFileEntry) {

    exportToFileEntry(savedFileEntry);

  } else {

    chrome.fileSystem.chooseEntry( {
      type: 'saveFile',
      suggestedName: 'todos.txt',
      accepts: [ { description: 'Text files (*.txt)',
                   extensions: ['txt']} ],
      acceptsAllTypes: true
    }, exportToFileEntry);

  }
}

chrome.fileSystem.chooseEntry() の最初のパラメータはオプションのオブジェクトです。2 つ目のパラメータはコールバック メソッドです。

すでに保存済みの FileEntry がある場合は、exportToFileEntry() を呼び出すときに代わりにそれを使用します。ファイル参照は、FileEntry を表すオブジェクトの存続期間中は存在します。この例では、FileEntry をアプリ ウィンドウに結び付けるため、アプリ ウィンドウが開いている限り、ユーザーの操作なしで選択されたファイルに JavaScript コードが書き込めます。

FileEntry を使用して ToDo アイテムをディスクに書き込む

FileEntry ウェブ API を介して exportToFileEntry() を更新して、Todo をテキストとして保存します。

function exportToFileEntry(fileEntry) {
  savedFileEntry = fileEntry;

  var status = document.getElementById('status');

  // Use this to get a file path appropriate for displaying
  chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
    fileDisplayPath = path;
    status.innerText = 'Exporting to '+path;
  });

  getTodosAsText( function(contents) {

    fileEntry.createWriter(function(fileWriter) {

      var truncated = false;
      var blob = new Blob([contents]);

      fileWriter.onwriteend = function(e) {
        if (!truncated) {
          truncated = true;
          // You need to explicitly set the file size to truncate
          // any content that might have been there before
          this.truncate(blob.size);
          return;
        }
        status.innerText = 'Export to '+fileDisplayPath+' completed';
      };

      fileWriter.onerror = function(e) {
        status.innerText = 'Export failed: '+e.toString();
      };

      fileWriter.write(blob);

    });
  });
}

chrome.fileSystem.getDisplayPath() は表示可能なファイルパスを取得し、ステータス div に出力します。

fileEntry.createWriter() を使用して FileWriter オブジェクトを作成します。これにより、fileWriter.write() はファイル システムに Blob を書き込むことができます。fileWriter.onwriteend()fileWriter.onerror() を使用して、ステータス div を更新します。

FileEntry の詳細については、HTML5Rocks の FileSystem API の確認または MDN の FileEntry docs をご覧ください。

FileEntry オブジェクトを保持する

高度: FileEntry オブジェクトを無期限に保持することはできません。アプリは、起動されるたびにユーザーにファイルの選択を求める必要があります。ランタイムのクラッシュまたは更新が原因でアプリが強制的に再起動された場合は、restoreEntry() を使用して FileEntry を復元できます。

必要に応じて、retainEntry() から返された ID を保存してテストし、アプリの再起動時に復元します。(ヒント: バックグラウンド ページの onRestarted イベントにリスナーを追加します)。

完成した ToDo アプリを起動する

ステップ 6 は完了です。アプリを再読み込みして、タスクを追加します。[ディスクにエクスポート] をクリックして、タスクを .txt ファイルにエクスポートします。

ToDo リストがエクスポートされた Todo アプリ

自然言語処理についてや、

この手順で導入する API の詳細については、以下をご覧ください。

次のステップに進む準備はできましたか?ステップ 7 - アプリを公開する »