Storage API

應用程式開發的每個環節都涉及傳送或接收資料的部分元素。從基礎概念開始,建議您使用 MVC 架構來設計及實作應用程式,使資料與該應用程式的資料檢視畫面完全分開 (請參閱 MVC 架構)。

此外,您必須考量應用程式離線時,系統如何處理資料 (請參閱「離線優先」一節)。本文件會簡要介紹用於在本機傳送、接收及儲存資料的儲存空間選項;本文件的其餘部分會說明如何使用 Chrome 的 File System API 和 Sync File System API (請參閱 fileSystem APIsyncFileSystem API)。

儲存空間選項

封裝應用程式使用多種不同機制來傳送和接收資料。如果是外部資料 (資源、網頁),您必須瞭解內容安全政策 (CSP)。與 Chrome 擴充功能類似,您可以使用跨來源 XMLHttpRequests 與遠端伺服器通訊。您也可以隔離外部網頁,確保應用程式的其餘部分安全無虞 (請參閱「嵌入外部網頁」)。

將資料儲存在本機時,您可以使用 Chrome Storage API 來儲存少量字串資料和 IndexedDB 來儲存結構化資料。透過 IndexedDB,您可以將 JavaScript 物件保存在物件儲存庫中,並使用商店的索引查詢資料 (詳情請參閱 HTML5 Rock 的簡易待辦事項清單教學課程)。若是二進位資料等所有其他類型的資料,請使用檔案系統和同步處理檔案系統 API。

Chrome 的檔案系統和同步檔案系統 API 會擴充 HTML5 FileSystem API。透過 Chrome 的檔案系統 API,應用程式可以建立、讀取、瀏覽及寫入使用者本機檔案系統的沙箱部分。舉例來說,相片分享應用程式可以使用 Filesystem API 讀取及寫入使用者選取的所有相片。

透過 Chrome 的 Sync Filesystem API,應用程式可以儲存及同步處理使用者的 Google 雲端硬碟資料,以便在不同用戶端存取相同的資料。例如,雲端支援文字編輯器應用程式會自動將新的文字檔案同步到使用者的 Google 雲端硬碟帳戶。當使用者在新用戶端中開啟文字編輯器時,Google 雲端硬碟會將新的文字檔案推送至該文字編輯器的執行個體。

使用 Chrome Filesystem API

新增檔案系統權限

如要使用 Chrome 的 File System API,您必須將「fileSystem」權限新增至資訊清單,才能向使用者取得儲存永久資料的權限。

"permissions": [
  "...",
  "fileSystem"
]

用於選取檔案的使用者選項

使用者會預期以平常的方式來選取檔案。至少需要「選擇檔案」按鈕和標準檔案選擇工具。如果應用程式會大量使用檔案處理功能,建議您一併實作拖曳功能 (請參閱下方的原生 HTML5 拖曳功能)。

取得檔案項目的路徑

如要取得使用者所選檔案的完整路徑,請呼叫 getDisplayPath()fileEntry

function displayPath(fileEntry) {
  chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
    console.log(path)
  });
}

實作拖曳功能

如果您需要實作拖曳選取功能,不妨從「filesystem-access」範例中的拖曳檔案控制器 (dnd.js) 開始著手。控制器會透過拖曳功能,從 DataTransferItem 建立檔案項目。在這個範例中,fileEntry 已設為第一個捨棄的項目。

var dnd = new DnDFileController('body', function(data) {
  var fileEntry = data.items[0].webkitGetAsEntry();
  displayPath(fileEntry);
});

讀取檔案

下列程式碼會開啟檔案 (唯讀),並使用 FileReader 物件以文字形式讀取檔案。如果檔案不存在,系統會擲回錯誤。

var chosenFileEntry = null;

chooseFileButton.addEventListener('click', function(e) {
  chrome.fileSystem.chooseEntry({type: 'openFile'}, function(readOnlyEntry) {

    readOnlyEntry.file(function(file) {
      var reader = new FileReader();

      reader.onerror = errorHandler;
      reader.onloadend = function(e) {
        console.log(e.target.result);
      };

      reader.readAsText(file);
    });
    });
});

撰寫檔案

兩種常見的檔案寫入用途是使用「儲存」和「另存新檔」。下列程式碼會從唯讀 chosenFileEntry 建立 writableEntry,並將所選檔案寫入其中。

 chrome.fileSystem.getWritableEntry(chosenFileEntry, function(writableFileEntry) {
    writableFileEntry.createWriter(function(writer) {
      writer.onerror = errorHandler;
      writer.onwriteend = callback;

    chosenFileEntry.file(function(file) {
      writer.write(file);
    });
  }, errorHandler);
});

以下程式碼會建立一個具備「另存新檔」功能的新檔案,並使用 writer.write() 方法將新的 blob 寫入該檔案。

chrome.fileSystem.chooseEntry({type: 'saveFile'}, function(writableFileEntry) {
    writableFileEntry.createWriter(function(writer) {
      writer.onerror = errorHandler;
      writer.onwriteend = function(e) {
        console.log('write complete');
      };
      writer.write(new Blob(['1234567890'], {type: 'text/plain'}));
    }, errorHandler);
});

使用 Chrome Sync Filesystem API

使用可同步檔案儲存空間處理傳回的資料物件,其運作方式與 FileSystem API 中的本機離線檔案系統相同,只是要將資料新增 (及自動) 同步處理至 Google 雲端硬碟。

新增同步檔案系統權限

如要使用 Chrome 的 Sync Filesystem API,您必須將「syncFileSystem」權限新增至資訊清單,才能取得使用者的權限來儲存及同步處理永久資料。

"permissions": [
  "...",
  "syncFileSystem"
]

正在啟動可同步處理的檔案儲存空間

如要在應用程式中啟動可同步處理的檔案儲存空間,只要呼叫 syncFileSystem.requestFileSystem 即可。這個方法會傳回 Google 雲端硬碟支援的可同步檔案系統,例如:

chrome.syncFileSystem.requestFileSystem(function (fs) {
   // FileSystem API should just work on the returned 'fs'.
   fs.root.getFile('test.txt', {create:true}, getEntryCallback, errorCallback);
});

關於檔案同步處理狀態

使用 syncFileSystem.getFileStatus 取得目前檔案的同步處理狀態:

chrome.syncFileSystem.getFileStatus(entry, function(status) {...});

檔案同步處理狀態可能是下列其中一種值:'synced''pending''conflicting'。「已同步」表示檔案已完全同步處理,沒有待處理的本機變更尚未同步到 Google 雲端硬碟。不過,Google 雲端硬碟端可能會出現尚未擷取的待處理變更。

「待處理」表示檔案尚未同步處理至 Google 雲端硬碟。如果應用程式在線上執行,本機變更幾乎會立即同步到 Google 雲端硬碟,且會觸發 syncFileSystem.onFileStatusChanged 事件,並顯示 'synced' 狀態 (詳情請參閱下文)。

當檔案的狀態變更為 'conflicting' 時,會觸發 syncFileSystem.onFileStatusChanged。「衝突」表示本機儲存空間與 Google 雲端硬碟有互相衝突的變更。只有在衝突解決政策設為 'manual' 時,檔案才能處於這個狀態。預設政策為 'last_write_win',且會透過簡單的最後寫入-勝出政策自動解決衝突。系統的衝突解決政策可以透過 syncFileSystem.setConflictResolutionPolicy 變更。

如果衝突解決政策設為 'manual',且檔案產生 'conflicting' 狀態,應用程式仍可讀取及寫入檔案做為本機離線檔案,但系統不會同步處理變更,且檔案會保留在其他用戶端上的遠端變更,直到衝突解決為止。解決衝突最簡單的方法,就是刪除或重新命名本機版本的檔案。這會強制同步處理遠端版本、解析衝突狀態,並以 'synced' 狀態觸發 onFileStatusChanged 事件。

監聽同步狀態的變更

檔案的同步狀態變更時,就會觸發 syncFileSystem.onFileStatusChanged 事件。 舉例來說,假設檔案有待變更項目且處於「待處理」狀態,應用程式可能為離線狀態,因此系統即將同步處理變更。當同步處理服務偵測到待處理的本機變更並將變更上傳至 Google 雲端硬碟時,服務就會觸發 onFileStatusChanged 事件,值如下:{ fileEntry:a fileEntry for the file, status: 'synced', action: 'updated', direction: 'local_to_remote' }

同樣地,無論本機活動為何,同步處理服務可能會偵測其他用戶端進行的遠端變更,並將變更從 Google 雲端硬碟下載至本機儲存空間。如果遠端變更是新增檔案,就會觸發包含下列值的事件:{ fileEntry: a fileEntry for the file, status: 'synced', action: 'added', direction: 'remote_to_local' }

如果本機和遠端端對同一個檔案有衝突的變更,且衝突解決政策設為 'manual',檔案狀態就會變更為 conflicting 狀態,就會從同步服務卸離,而且要等到衝突解決後才會同步處理。在此情況下,觸發以下值的事件:{ fileEntry: a fileEntry for the file, status: 'conflicting', action: null, direction: null }

您可以為這個事件新增一個回應狀態變更的事件監聽器。舉例來說,Chrome 音樂播放器應用程式會監聽從 Google 雲端硬碟同步的任何新音樂,但尚未匯入到特定用戶端的本機儲存空間。系統會將找到的任何音樂同步處理至該用戶端:

chrome.syncFileSystem.onFileStatusChanged.addListener(function(fileInfo) {
  if (fileInfo.status === 'synced') {
    if (fileInfo.direction === 'remote_to_local') {
      if (fileInfo.action === 'added') {
        db.add(fileInfo.fileEntry);
      } else if (fileInfo.action === 'deleted') {
        db.remove(fileInfo.fileEntry);
      }
    }
  }
});

檢查 API 用量

如要查看 API 使用的資料量,請查詢應用程式的本機沙箱目錄或 syncFileSystem.getUsageAndQuota 傳回的用量位元組:

chrome.syncFileSystem.getUsageAndQuota(fileSystem, function (storageInfo) {
   updateUsageInfo(storageInfo.usageBytes);
   updateQuotaInfo(storageInfo.quotaBytes);
});

您也可以查看使用者的同步後端服務儲存空間 (Google 雲端硬碟)。同步的檔案會儲存在隱藏的 Google 雲端硬碟資料夾「Chrome 可同步檔案系統」中。該資料夾不會顯示在「我的雲端硬碟」清單中,但只要在搜尋框中搜尋資料夾名稱,就能存取該資料夾。(請注意,遠端資料夾的版面配置「無法」保證在不同版本之間維持回溯相容性)。