估算可用儲存空間

Jeff Posnick
Jeff Posnick

重點摘要

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 和一些圖片Service WorkerCache Storage API 提供儲存核心資源所需的基礎架構, 以便稍後快速載入您的網路應用程式,最好完全略過網路。 (與網頁應用程式的建構程序整合的工具, Workbox 程式庫 sw-precache、 可以完全自動化處理儲存、更新並使用這類型的 data.)

但其他類型的資料呢?您不一定要使用這些資源 但是這對您的整體使用者來說可能 是重要角色 無須專人管理舉例來說,如果您正在編寫圖片編輯網頁應用程式 想儲存圖片的一或多個本機副本,讓使用者能 以及復原作業或者,如果你開發離線媒體 因此將音訊或影片檔案儲存在本機上, 而不是每個特徵的分數凡是可個人化的網頁應用程式,最終都需要儲存一些設定 狀態資訊。 如何得知這類執行階段儲存空間還有多少可用空間? 儲存空間用盡時會發生什麼情況?

過去:window.webkitStorageInfonavigator.webkitTemporaryStorage

瀏覽器一直以來都透過前置字串 例如舊版 (和已淘汰) 的介面 window.webkitStorageInfo、 和不等式,但仍然非標準 navigator.webkitTemporaryStorage。 雖然這些介面可提供實用資訊,但實際上 未來將成為網路標準

這就是 WHATWG 儲存空間標準 輸入圖片。

未來趨勢: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 則是代表 目前可儲存的位元組上限 origin。 (如同其他與儲存空間相關的問題,配額適用於整個 origin.)

如果網頁應用程式嘗試儲存資料 (例如使用 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 可反映指定來源有效用於 相同來源 資料,因此可能會受到內部壓縮技術的影響 固定大小分配區塊,可能含有未使用的空間 的 "Tombstone"記錄 也可能在刪除後暫時建立避免資訊外洩 例如確切大小資訊、跨來源 不透明資源 儲存在本機中,可能會為整體 usage 產生額外的邊框間距位元組 值。
  • quota 反映目前為來源預留的空間大小。 值取決於一些固定因素,例如整體儲存空間大小 可能造成波動的因素數量,包括儲存空間容量 目前未使用的 Pod因此,裝置上的其他應用程式會寫入或刪除 資料,瀏覽器願意佔用網路的空間 應用程式的來源可能會變更。

簡報內容:功能偵測和備用

從 Chrome 61 版開始,estimate()會預設為啟用。Firefox 為 但自 2017 年 8 月起,不再開啟「navigator.storage」 預設為啟用。您需要執行的操作 啟用 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});
}