網頁平台提供的工具越來越多,可協助開發人員建構微調過的高效能網頁應用程式。最值得一提的是,WebAssembly (Wasm) 為快速且功能強大的網路應用程式開啟了大門,而 Emscripten 等技術則讓開發人員能在網路上重複使用經過測試的程式碼。如要充分發揮這項潛力,開發人員在儲存空間方面也必須擁有相同的能力和彈性。
這時 Storage Foundation API 就能派上用場。Storage Foundation API 是全新的快速儲存空間 API,可支援網路上許多新用途,例如實作高效能資料庫,以及妥善管理大型暫時檔案。透過這個新介面,開發人員可以「自備儲存空間」到網頁,縮小網頁與平台專屬程式碼之間的差距。
Storage Foundation API 的設計類似於非常基本的檔案系統,因此可提供一般、簡單且高效能的基元,讓開發人員建構更高層級的元件,進而享有彈性。應用程式可根據需求選擇最合適的工具,在可用性、效能和穩定性之間取得適當平衡。
為什麼網頁需要其他儲存空間 API?
網頁平台為開發人員提供多種儲存空間選項,每種選項都是針對特定用途而建構。
- 其中有些選項顯然與這項提案不重疊,因為這些選項只允許儲存極少量資料,例如 Cookie,或是由
sessionStorage
和localStorage
機制組成的 Web Storage API。 - 其他選項已因各種原因遭到淘汰,例如 File and Directory Entries API 或 WebSQL。
- 檔案系統存取 API 具有類似的 API 介面,但其用途是與用戶端的檔案系統介接,並提供對資料的存取權,這些資料可能不在來源或甚至瀏覽器的擁有權範圍內。這種不同的重點會帶來更嚴格的安全考量,以及更高的效能成本。
- IndexedDB API 可做為部分 Storage Foundation API 用途的後端。舉例來說,Emscripten 包含以 IndexedDB 為基礎的持續性檔案系統 IDBFS。不過,由於 IndexedDB 本質上是鍵值儲存空間,因此有顯著的效能限制。此外,在 IndexedDB 中直接存取檔案的子區段更加困難,速度也較慢。
- 最後,CacheStorage 介面受到廣泛支援,且經過調整,可儲存大型資料 (例如網頁應用程式資源),但值是不可變動的。
Storage Foundation API 旨在填補先前儲存空間選項的所有缺口,允許在應用程式來源中定義的可變動大型檔案,以高效能方式儲存。
Storage Foundation API 的建議用途
可能使用這項 API 的網站包括:
- 處理大量影片、音訊或圖片資料的生產力或創意應用程式。這類應用程式可將區隔卸載至磁碟,而非保留在記憶體中。
- 應用程式依賴可從 Wasm 存取的永久檔案系統,且需要的效能高於 IDBFS 保證的效能。
什麼是 Storage Foundation API?
這個 API 分為兩大部分:
- 檔案系統呼叫:提供與檔案和檔案路徑互動的基本功能。
- 檔案控制代碼:提供現有檔案的讀寫權限。
檔案系統呼叫
Storage Foundation API 導入了新的物件 storageFoundation
,這個物件位於 window
物件上,並包含多項函式:
storageFoundation.open(name)
:開啟指定名稱的檔案 (如果存在),否則會建立新檔案。傳回以開啟的檔案解析的 Promise。
storageFoundation.delete(name)
:移除指定名稱的檔案。傳回在檔案刪除時解析的 Promise。storageFoundation.rename(oldName, newName)
:以不可分割的方式將檔案從舊名稱重新命名為新名稱。傳回在檔案重新命名時解析的 Promise。storageFoundation.getAll()
:傳回 Promise,並以所有現有檔案名稱的陣列解析。storageFoundation.requestCapacity(requestedCapacity)
:要求目前執行環境的新容量 (以位元組為單位)。傳回承諾,並以剩餘可用容量解析。
storageFoundation.releaseCapacity(toBeReleasedCapacity)
:從目前的執行環境釋出指定位元組數,並傳回會以剩餘容量解析的 Promise。storageFoundation.getRemainingCapacity()
:傳回 Promise,該 Promise 會解析目前執行環境可用的容量。
檔案控制代碼
您可以使用下列函式處理檔案:
NativeIOFile.close()
:關閉檔案,並傳回在作業完成時會解析的 Promise。NativeIOFile.flush()
:將檔案的記憶體內狀態與儲存裝置同步 (即清除),並在作業完成時傳回已解決的 Promise。
NativeIOFile.getLength()
:傳回 Promise,並以檔案長度 (以位元組為單位) 解析。NativeIOFile.setLength(length)
:以位元組為單位設定檔案長度,並傳回作業完成時會解析的 Promise。如果新長度小於目前長度,系統會從檔案結尾開始移除位元組。否則檔案會以零值位元組擴充。NativeIOFile.read(buffer, offset)
:透過緩衝區讀取指定位移處的檔案內容,該緩衝區是轉移指定緩衝區的結果,之後會保持分離狀態。傳回NativeIOReadResult
,其中包含已轉移的緩衝區和成功讀取的位元組數。NativeIOReadResult
是由兩個項目組成的物件:buffer
:ArrayBufferView
,這是將緩衝區傳遞至read()
的結果。與來源緩衝區的類型和長度相同。readBytes
:成功讀取到buffer
中的位元組數。如果發生錯誤,或讀取範圍超出檔案結尾,這個值可能會小於緩衝區大小。如果讀取範圍超出檔案結尾,則會設為零。
NativeIOFile.write(buffer, offset)
:將指定緩衝區的內容寫入指定偏移位置的檔案。緩衝區會在寫入任何資料前轉移,因此會保持分離狀態。傳回NativeIOWriteResult
,其中包含已轉移的緩衝區和成功寫入的位元組數。如果寫入範圍超出檔案長度,檔案就會擴增。NativeIOWriteResult
是由兩個項目組成的物件:buffer
:ArrayBufferView
,這是將緩衝區傳遞至write()
的結果。與來源緩衝區的類型和長度相同。writtenBytes
:成功寫入buffer
的位元組數。如果發生錯誤,這個值可能會小於緩衝區大小。
完整範例
為清楚說明上述概念,以下提供兩個完整範例,逐步介紹 Storage Foundation 檔案生命週期的不同階段。
開啟、寫入、讀取、關閉
// Open a file (creating it if needed).
const file = await storageFoundation.open('test_file');
try {
// Request 100 bytes of capacity for this context.
await storageFoundation.requestCapacity(100);
const writeBuffer = new Uint8Array([64, 65, 66]);
// Write the buffer at offset 0. After this operation, `result.buffer`
// contains the transferred buffer and `result.writtenBytes` is 3,
// the number of bytes written. `writeBuffer` is left detached.
let result = await file.write(writeBuffer, 0);
const readBuffer = new Uint8Array(3);
// Read at offset 1. `result.buffer` contains the transferred buffer,
// `result.readBytes` is 2, the number of bytes read. `readBuffer` is left
// detached.
result = await file.read(readBuffer, 1);
// `Uint8Array(3) [65, 66, 0]`
console.log(result.buffer);
} finally {
file.close();
}
開啟、列出、刪除
// Open three different files (creating them if needed).
await storageFoundation.open('sunrise');
await storageFoundation.open('noon');
await storageFoundation.open('sunset');
// List all existing files.
// `["sunset", "sunrise", "noon"]`
await storageFoundation.getAll();
// Delete one of the three files.
await storageFoundation.delete('noon');
// List all remaining existing files.
// `["sunrise", "noon"]`
await storageFoundation.getAll();
安全性和權限
Chromium 團隊採用「控管強大的網頁平台功能存取權」中定義的核心原則 (包括使用者控制權、透明度和人體工學),設計及實作 Storage Foundation API。
與網路上其他新式儲存空間 API 相同,Storage Foundation API 的存取權會受到來源限制,也就是說,來源只能存取自行建立的資料。此外,也僅限於安全環境。
使用者控制項
儲存空間配額用於分配磁碟空間存取權,並防止濫用。您必須先要求要占用的記憶體,與其他儲存空間 API 相同,使用者可以透過瀏覽器清除 Storage Foundation API 占用的空間。
實用連結
- 公開說明
- Chromium 追蹤錯誤
- ChromeStatus.com 項目
- Blink 元件:
Blink>Storage>NativeIO
- TAG 審查
- Intent to Prototype
- WebKit 執行緒
- Mozilla 執行緒
特別銘謝
Storage Foundation API 由 Emanuel Krivoy 和 Richard Stotz 負責指定及實作。本文由 Pete LePage 和 Joe Medley 審查。
主頁橫幅圖片由 Markus Spiske 提供,刊登於 Unsplash。