網頁平台提供的工具越來越多,開發人員可以利用這些工具,為網頁建構精密調校的高效能應用程式。最值得一提的是,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。
- File System Access API 具有類似的 API 介面,但其用途是與用戶端的檔案系統進行介面連結,並提供對來源或瀏覽器擁有權以外的資料存取權。這類不同的重點會帶來更嚴格的安全考量和更高的效能成本。
- IndexedDB API 可用於部分 Storage Foundation API 用途的後端。舉例來說,Emscripten 包含 IDBFS,這是以 IndexedDB 為基礎的持續性檔案系統。不過,由於 IndexedDB 基本上是鍵/值儲存庫,因此成效會受到重大限制。此外,在 IndexedDB 中直接存取檔案的子區段更是難上加難,速度也更慢。
- 最後,CacheStorage 介面廣泛支援,並經過調整,可用於儲存大型資料 (例如網頁應用程式資源),但值無法變更。
Storage Foundation API 可讓應用程式原點定義的變動大型檔案以高效的方式儲存,藉此填補先前儲存空間選項的所有缺口。
Storage Foundation API 的建議用途
以下是可能會使用這個 API 的網站:
- 以大量影片、音訊或圖片資料運作的生產力或創意應用程式。這類應用程式可以將區段卸載至磁碟,而非保留在記憶體中。
- 應用程式會依賴可從 Wasm 存取的永久檔案系統,且需要的效能高於 IDBFS 可保證的效能。
什麼是 Storage Foundation API?
API 包含兩個主要部分:
- 檔案系統呼叫:提供與檔案和檔案路徑互動的基礎功能。
- 檔案句柄:提供現有檔案的讀取和寫入存取權。
檔案系統呼叫
Storage Foundation API 會引入新的物件 storageFoundation
,該物件位於 window
物件上,並包含多項功能:
storageFoundation.open(name)
:如果檔案名稱已存在,就會開啟該檔案,否則會建立新檔案。傳回會與已開啟檔案解析的承諾。
storageFoundation.delete(name)
:移除指定名稱的檔案。傳回的承諾會在檔案刪除時解析。storageFoundation.rename(oldName, newName)
:將檔案從舊名稱重新命名為新名稱。傳回一個承諾,在檔案重新命名時解析。storageFoundation.getAll()
:傳回承諾,該承諾會以所有現有檔案名稱的陣列解析。storageFoundation.requestCapacity(requestedCapacity)
:要求新的容量 (以位元組為單位),供目前執行階段使用。傳回已解決的承諾,其中包含可用的剩餘容量。
storageFoundation.releaseCapacity(toBeReleasedCapacity)
:從目前的執行內容釋出指定位元組數量,並傳回會以剩餘容量解析的承諾。storageFoundation.getRemainingCapacity()
:傳回承諾,該承諾會根據目前執行作業情境的可用容量解析。
檔案句柄
您可以透過下列函式使用檔案:
NativeIOFile.close()
:關閉檔案,並傳回在作業完成時解析的承諾。NativeIOFile.flush()
:將檔案的記憶體內狀態與儲存裝置同步 (也就是刷新),並傳回在作業完成時解析的承諾。
NativeIOFile.getLength()
:傳回以位元組為單位的檔案長度,並解析該長度。NativeIOFile.setLength(length)
:以位元組為單位設定檔案長度,並傳回在作業完成時解析的承諾。如果新長度小於目前長度,系統會從檔案結尾開始移除位元組。否則,檔案會使用零值位元組延伸。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();
示範
您可以透過下方嵌入的 Storage Foundation API 示範進行操作。建立、重新命名、寫入及讀取檔案,並在變更時查看您要求更新的可用容量。您可以在 Glitch 上找到示範的原始碼。
安全性和權限
Chromium 團隊根據「控管強大網頁平台功能的存取權」一文中定義的核心原則,設計並實作 Storage Foundation API,包括使用者控管、資訊公開和人因工程。
與網站上其他新式儲存空間 API 相同,Storage Foundation API 的存取權受限於來源,也就是說,來源只能存取自行建立的資料。且僅限於安全的內容。
使用者控制項
儲存空間配額可用於分配磁碟空間存取權,並防止濫用行為。您必須先要求要佔用的記憶體。如同其他儲存空間 API,使用者可以透過瀏覽器清除 Storage Foundation API 占用的空間。
實用連結
- 公開說明
- Storage Foundation API 示範 | Storage Foundation API 示範來源
- Chromium 追蹤錯誤
- ChromeStatus.com 項目
- Blink 元件:
Blink>Storage>NativeIO
- TAG 審查
- 意圖製作原型
- WebKit 執行緒
- Mozilla 執行緒
特別銘謝
Emanuel Krivoy 和 Richard Stotz 指定並實作了 Storage Foundation API。本文由 Pete LePage 和 Joe Medley 審查。
主頁橫幅圖片由 Markus Spiske 提供,取自 Unsplash。