useDecryptedAsset()
useDecryptedAsset 是 SwImage、SwAsyncText 共用的底層 composable,把「遠端資源載入 → 條件 AES 解密 → IndexedDB 持久化快取 → 狀態機」這套通用邏輯抽出來。業務層一般不直接呼叫,但需要自訂加密資源載入場景(自管 store 表、自訂編碼格式)時可以直接用。
使用方式
真實 .bnc 解密(status + result)
加载中...
透過 toCache / fromCache 兩個鉤子讓呼叫方決定快取格式與業務結果格式:
// 範例 1:加密圖片 → Blob URL(SwImage 內部就這麼用)
const { status, result: blobUrl } = useDecryptedAsset<Blob, string>({
url: computed(() => props.src),
key: imgKey,
table: 'image',
toCache: buf => new Blob([buf], { type: detectMime(buf) }),
fromCache: blob => URL.createObjectURL(blob),
})
// 範例 2:加密文字 → 字串(響應式監聽 url 變化,SwAsyncText 內部用法)
const { result: text } = useDecryptedAsset<Uint8Array, string>({
url: computed(() => props.url),
key: imgKey,
table: 'text',
toCache: buf => new Uint8Array(buf),
fromCache: bytes => new TextDecoder().decode(bytes),
reactive: true,
})
工作原理
- SSR 短路:
import.meta.server為true時直接 return,status保持'loading',不發起任何網路請求與解密 - 快取查詢:
fileId = md5(new URL(url).pathname).toUpperCase(),先查 IndexedDB 對應 store 表;命中走fromCache(data)回傳業務結果 - 遠端載入 + 條件解密:未命中則
fetch(url)拿到ArrayBuffer;url含.bnc走decryptBinary(buf, key),否則跳過解密直接走toCache - 寫快取:
toCache編碼後的資料寫入 IndexedDB(下次秒開),同時result從null→ 業務結果,status從'loading'→'loaded'。寫快取是可降級旁路——不 await(渲染不等 DB),且寫入失敗會被靜默忽略(fw#380) - 響應式重載:
reactive: true時用watchEffect監聽url響應式變化,自動重新執行流程;false(預設)時僅onMounted觸發一次
Options
| 名稱 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
url | MaybeRef<string> | ✓ | — | 資源 URL,可傳響應式(Ref / computed) |
key | string | ✓ | — | AES 解密金鑰。僅 .bnc URL 實際使用;非加密路徑忽略此值,但仍需傳 |
table | 'image' | 'text' | ✓ | — | IndexedDB store 表名。約定兩個:'image' 給圖片類資源,'text' 給文字類 |
toCache | (buffer: ArrayBuffer) => TCached | ✓ | — | 把解密後的 ArrayBuffer 編碼為快取格式(如 new Blob([buf]) / new Uint8Array(buf)) |
fromCache | (cached: TCached) => TResult | ✓ | — | 把快取格式解碼為業務結果(如 URL.createObjectURL(blob) / new TextDecoder().decode(bytes)) |
reactive | boolean | false | true 用 watchEffect 監聽 url 響應式變化;false 僅 onMounted 觸發一次 |
回傳值
| 名稱 | 類型 | 說明 |
|---|---|---|
status | Ref<'loading' | 'loaded' | 'error'> | 目前載入狀態。SSR 階段始終為 'loading' |
result | Ref<TResult | null> | 解碼後的業務結果。null 表示載入中(或 SSR),非 null 即就緒 |
注意事項
- 僅用戶端執行——依賴 IndexedDB / fetch / Web Crypto。SSR 階段函式直接 return,呼叫方
status保持'loading',請用result === null提供骨架佔位 - 加密分流由 url 自動判定:含
.bnc走解密,否則跳過——呼叫方無需再判斷 - dbGet/dbPut 的資料結構約定為
{ id: string, data: TCached },與現有SwImage/SwAsyncText快取格式相容 - 寫快取失敗會被靜默忽略(fw#380):不影響本次算繪(
result來自記憶體中的cacheData),也不會冒泡成unhandledrejection汙染errorHandler的上報。典型觸發面是 WebKit 儲存受限環境(爬蟲 / Safari 隱私模式 / 受限 WebView)寫 Blob 進 IndexedDB。讀取快取失敗時視為未命中,繼續遠端載入;網路、解密或格式轉換失敗仍進入status='error' - 未來擴充 store 表名時需要同步在
framework/src/runtime/utils/db.ts裡登記 schema,否則 IndexedDB 寫入會失敗 - 過期請求隔離:每次載入先清空舊結果並進入
loading,只有最新請求可更新結果與狀態。切換至空 URL 或作用域銷毀後,舊請求不再回填;已發出的網路請求不會主動取消。