步驟 6:將待辦事項匯出至檔案系統

在這個步驟中,您將瞭解以下內容:

  • 如何取得外部檔案系統中檔案的參照。
  • 如何寫入檔案系統。

完成這個步驟所需的時間:20 分鐘。
如要預覽您將在這個步驟中完成的內容,請向下捲動到本頁底部 ↓。

匯出待辦事項

這個步驟會在應用程式中新增匯出按鈕。點選之後,系統會將目前的待辦事項儲存至一段文字 使用者選取的檔案如果檔案已存在,則系統會取代該檔案。否則,系統會建立新檔案。

更新權限

您可以要求以字串形式要求檔案系統權限,或要求選取 例如:

// 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.html 中,載入 export.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()、exportToFileEntry 和 doExportToDisk()。

以文字顯示待辦事項

更新 getTodosAsText(),使其讀取 chrome.storage.local 中的待辦事項並產生文字 其表示法:

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));
}

選擇檔案

使用 chrome.fileSystem.chooseEntry() 更新 doExportToDisk(),讓使用者選擇 檔案:

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() 的第一個參數是選項物件。第二個 參數是一種回呼方法。

如果已有已儲存的 FileEntry,請在呼叫 exportToFileEntry() 時改用該名稱。檔案 參照的存在於物件生命週期內,都存在於代表 FileEntry 的物件生命週期內。這個範例 將 FileEntry 傳送至應用程式視窗,讓 JavaScript 程式碼無需使用者就能寫入所選檔案 則可維持在開啟狀態。

使用 FileEntry 將待辦事項項目寫入磁碟

更新 exportToFileEntry(),透過 FileEntry Web API 將待辦事項儲存為文字:

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 上的「探索檔案系統 API」,或是 請參閱 MDN 上的 FileEntry docs。

保留 FileEntry 物件

進階:FileEntry 物件無法無限期保存。應用程式必須要求使用者 每次啟動應用程式時選擇檔案如果應用程式因執行階段而強制重新啟動 當機或更新時,restoreEntry() 可用來還原 FileEntry。

如有需要,您可以嘗試儲存 retainEntry() 傳回的 ID,並在應用程式中還原該 ID 重新啟動。(提示:將事件監聽器新增至背景頁面的 onRestarted 事件)。

啟動已完成的 Todo 應用程式

您已完成步驟 6!重新載入應用程式並加入待辦事項。按一下「匯出至磁碟」以匯出您的 寫入 .txt 檔案

含有已匯出待辦事項的 Todo 應用程式

瞭解詳情

如要進一步瞭解這個步驟中導入的部分 API,請參閱:

準備好進行下一個步驟了嗎?前往步驟 7 - 發布應用程式 »