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,
})

工作原理

  1. SSR 短路:import.meta.server 為 true 時直接 return,status 保持 'loading',不發起任何網路請求與解密
  2. 快取查詢:fileId = md5(new URL(url).pathname).toUpperCase(),先查 IndexedDB 對應 store 表;命中走 fromCache(data) 回傳業務結果
  3. 遠端載入 + 條件解密:未命中則 fetch(url) 拿到 ArrayBuffer;url 含 .bnc 走 decryptBinary(buf, key),否則跳過解密直接走 toCache
  4. 寫快取:toCache 編碼後的資料寫入 IndexedDB(下次秒開),同時 result 從 null → 業務結果,status 從 'loading' → 'loaded'。寫快取是可降級旁路——不 await(渲染不等 DB),且寫入失敗會被靜默忽略(fw#380)
  5. 響應式重載:reactive: true 時用 watchEffect 監聽 url 響應式變化,自動重新執行流程;false(預設)時僅 onMounted 觸發一次

Options

名稱類型必填預設值說明
urlMaybeRef<string>✓—資源 URL,可傳響應式(Ref / computed)
keystring✓—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))
reactivebooleanfalsetrue 用 watchEffect 監聽 url 響應式變化;false 僅 onMounted 觸發一次

回傳值

名稱類型說明
statusRef<'loading' | 'loaded' | 'error'>目前載入狀態。SSR 階段始終為 'loading'
resultRef<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 或作用域銷毀後,舊請求不再回填;已發出的網路請求不會主動取消。