估算可用儲存空間

重點摘要

Chrome 61 和更多瀏覽器現在會顯示預估值,說明網頁應用程式使用的儲存空間大小,以及可用的儲存空間大小:

if ('storage' in navigator && 'estimate' in navigator.storage) {
  navigator.storage.estimate().then(({usage, quota}) => {
    console.log(`Using ${usage} out of ${quota} bytes.`);
  });
}

現代化的網頁應用程式和資料儲存空間

在思考現代網頁應用程式的儲存需求時,建議將儲存的內容分為兩類:載入網頁應用程式所需的核心資料,以及應用程式載入後用於有意義的使用者互動所需的資料。

第一類資料是載入網頁應用程式所需的資料,包括 HTML、JavaScript、CSS 和一些圖片。服務工作者快取儲存空間 API 可提供必要的基礎架構,用於儲存這些核心資源,並在日後用於快速載入網路應用程式,最好是完全略過網路。(與您網頁應用程式建構程序整合的工具 (例如新的 Workbox 程式庫或較舊的 sw-precache) 可完全自動化這類資料的儲存、更新和使用程序。)

那麼其他類型的資料呢?這些資源並非載入網頁應用程式所需,但可能在整體使用者體驗中扮演重要角色。舉例來說,如果您要編寫圖片編輯網頁應用程式,可能會想儲存一或多個圖片的本機副本,讓使用者在修訂版本之間切換,並撤銷作業。或者,如果您要開發離線媒體播放體驗,則在本機儲存音訊或視訊檔案是一項重要功能。每個可進行個人化的網頁應用程式都需要儲存某種狀態資訊。如何得知這類執行階段儲存空間的可用空間,以及空間用盡時會發生什麼事?

過去:window.webkitStorageInfonavigator.webkitTemporaryStorage

瀏覽器一向透過前置字串介面支援這類自省功能,例如非常舊 (且已淘汰) 的 window.webkitStorageInfo,以及不那麼舊但仍非標準的 navigator.webkitTemporaryStorage。雖然這些介面提供了實用的資訊,但未來不會成為網路標準。

這時就需要使用 WHATWG Storage Standard

未來:navigator.storage

Storage Living Standard 的持續性工作中,有幾個實用的 API 已納入 StorageManager 介面,並以 navigator.storage 的形式公開給瀏覽器。與許多其他較新的網路 API 一樣,navigator.storage 僅適用於安全 (透過 HTTPS 或 localhost 提供服務) 的來源。

我們在去年推出 navigator.storage.persist() 方法,讓您的網頁應用程式可要求將其儲存空間排除在自動清理作業之外。

這項功能現在已加入 navigator.storage.estimate() 方法,可做為 navigator.webkitTemporaryStorage.queryUsageAndQuota() 的現代替代方案。estimate() 會傳回類似的資訊,但會公開以承諾為基礎的介面,這與其他新型非同步 API 相符。estimate() 傳回的承諾會解析含有兩個屬性的物件:usage 代表目前使用的位元組數,quota 代表目前來源可儲存的位元組數上限。(如同其他儲存空間相關項目,配額會套用至整個來源)。

如果網路應用程式嘗試使用 IndexedDB 或 Cache Storage API 等方式儲存過大,導致特定來源超出可用配額的資料,要求就會失敗,並擲回 QuotaExceededError 例外狀況。

儲存空間估算值的實際運作情形

具體使用 estimate() 的方式取決於應用程式需要儲存的資料類型。舉例來說,您可以更新介面中的控制項,讓使用者知道每次儲存作業完成後,系統會使用多少空間。理想情況下,您應提供介面,讓使用者手動清理不再需要的資料。您可以編寫類似以下的程式碼:

// For a primer on async/await, see
// https://developers.google.com/web/fundamentals/getting-started/primers/async-functions
async function storeDataAndUpdateUI(dataUrl) {
  // Pro-tip: The Cache Storage API is available outside of service workers!
  // See https://googlechrome.github.io/samples/service-worker/window-caches/
  const cache = await caches.open('data-cache');
  await cache.add(dataUrl);

  if ('storage' in navigator && 'estimate' in navigator.storage) {
    const {usage, quota} = await navigator.storage.estimate();
    const percentUsed = Math.round(usage / quota * 100);
    const usageInMib = Math.round(usage / (1024 * 1024));
    const quotaInMib = Math.round(quota / (1024 * 1024));

    const details = `${usageInMib} out of ${quotaInMib} MiB used (${percentUsed}%)`;

    // This assumes there's a <span id="storageEstimate"> or similar on the page.
    document.querySelector('#storageEstimate').innerText = details;
  }
}

預估值的準確度如何?

您很難忽略從函式中傳回的資料,這只是來源使用的空間的估計值。函式名稱中就包含這個字串!usagequota 值都不會維持穩定,因此建議您考量以下事項:

  • usage 反映特定來源為同源資料有效使用的位元組數,這可能會受到內部壓縮技術、可能包含未使用的空間的固定大小配置區塊,以及在刪除後可能暫時建立的「墓碑」記錄的影響。為避免洩漏確切大小資訊,跨來源的不透明資源如果儲存在本機,可能會為整體 usage 值提供額外的填充位元組。
  • quota 反映目前為來源預留的空間量。這個值取決於一些常數因素 (例如整體儲存空間大小),以及一些可能會變動的因素,包括目前未使用的儲存空間量。因此,當裝置上的其他應用程式寫入或刪除資料時,瀏覽器願意用於網頁應用程式來源的空間量可能會有所變動。

現況:偵測功能和備用功能

estimate() 預設會在 Chrome 61 以上版本啟用。Firefox 正在測試 navigator.storage,但截至 2017 年 8 月,預設並未啟用。您必須啟用 dom.storageManager.enabled 偏好設定才能進行測試。

如果您要使用某項功能,但該功能尚未在所有瀏覽器中支援,就必須進行功能偵測。您可以將功能偵測功能與以承諾為基礎的包裝函式結合,並在舊版 navigator.webkitTemporaryStorage 方法上方提供一致的介面,如下所示:

function storageEstimateWrapper() {
  if ('storage' in navigator && 'estimate' in navigator.storage) {
    // We've got the real thing! Return its response.
    return navigator.storage.estimate();
  }

  if ('webkitTemporaryStorage' in navigator &&
      'queryUsageAndQuota' in navigator.webkitTemporaryStorage) {
    // Return a promise-based wrapper that will follow the expected interface.
    return new Promise(function(resolve, reject) {
      navigator.webkitTemporaryStorage.queryUsageAndQuota(
        function(usage, quota) {resolve({usage: usage, quota: quota})},
        reject
      );
    });
  }

  // If we can't estimate the values, return a Promise that resolves with NaN.
  return Promise.resolve({usage: NaN, quota: NaN});
}