feat(web): authed blob image pipeline with LRU, cover card, dir grouping
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { apiRaw } from "../api/client";
|
||||
|
||||
const MAX = 600;
|
||||
const cache = new Map<string, Promise<string>>(); // 插入序 ≈ LRU(命中时重插)
|
||||
|
||||
// 带鉴权取图 → objectURL。后端 Bearer-only,<img>/<iframe> 直挂 /api 必 401,
|
||||
// 故图片一律走此通道;URL 含内容 hash 不可变,会话内可安全长驻缓存。
|
||||
export async function fetchObjectUrl(url: string, signal?: AbortSignal): Promise<string> {
|
||||
const hit = cache.get(url);
|
||||
if (hit) {
|
||||
cache.delete(url);
|
||||
cache.set(url, hit);
|
||||
return hit;
|
||||
}
|
||||
const p = (async () => {
|
||||
const res = await apiRaw(url, { signal });
|
||||
return URL.createObjectURL(await res.blob());
|
||||
})();
|
||||
p.catch(() => cache.delete(url)); // 失败出缓存,下次调用重试
|
||||
cache.set(url, p);
|
||||
while (cache.size > MAX) {
|
||||
const oldest = cache.keys().next().value as string;
|
||||
cache.delete(oldest); // 不 revoke:可能仍被在屏 <img> 引用;≤600 条会话内 blob 可接受
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
export function __resetImageCache(): void {
|
||||
cache.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user