indexeddb 可直接存储 blob/file 对象,无需转 base64 或 arraybuffer;创建对象仓库时以字符串字段为 keypath,blob 作属性值存入,读取后用 url.createobjecturl() 播放并及时 revoke。

IndexedDB 可以直接存储 Blob 或 File 对象(本质都是 Blob),无需转成 base64 或 ArrayBuffer(除非有特殊需求),这是实现离线多媒体播放的关键基础。
1. 创建数据库并定义对象仓库(支持 Blob 存储)
IndexedDB 原生支持 Blob 类型,只要在 object store 中使用可键化(key-path)字段(如 id 或 name),Blob 就能作为值存入。注意:不能把 Blob 用作主键(因为不可序列化),但可作为普通属性值。
示例:
const request = indexedDB.open('mediaDB', 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
// 使用 'url' 作为 keyPath,便于按资源路径查询
if (!db.objectStoreNames.contains('videos')) {
const store = db.createObjectStore('videos', { keyPath: 'url' });
// 可选:添加索引,比如按类型或时间
store.createIndex('byType', 'type', { unique: false });
}
};
2. 存储 Blob(如视频/音频文件)
获取 Blob 后,直接将其作为 JS 对象属性写入记录。浏览器内部会自动处理二进制数据的持久化。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 从
<input type="file">或fetch()获取 Blob - 构造一个包含元信息(如 url、type、name)和 Blob 本身的数据对象
- 调用
put()写入 object store
示例(保存远程视频):
async function saveVideo(url) {
try {
const res = await fetch(url);
const blob = await res.blob();
const db = await getDb(); // 假设已有打开数据库的工具函数
const tx = db.transaction('videos', 'readwrite');
const store = tx.objectStore('videos');
const record = {
url,
type: blob.type,
size: blob.size,
timestamp: Date.now(),
data: blob // 直接存 Blob,不转换!
};
await store.put(record);
} catch (e) {
console.error('保存失败:', e);
}
}
3. 离线读取并播放 Blob
从 IndexedDB 读出记录后,其 data 字段仍是 Blob,可直接赋给 <video></video> 或 <audio></audio> 的 src 属性 —— 但需用 URL.createObjectURL() 创建临时内存 URL。
- 不要尝试把 Blob 转成 base64(浪费内存、慢、有长度限制)
-
createObjectURL()开销小,且浏览器会自动管理生命周期 - 播放结束后建议调用
URL.revokeObjectURL()释放引用(尤其多文件场景)
示例:
async function playOfflineVideo(url) {
const db = await getDb();
const tx = db.transaction('videos', 'readonly');
const store = tx.objectStore('videos');
const record = await store.get(url);
if (record && record.data instanceof Blob) {
const video = document.getElementById('player');
const blobUrl = URL.createObjectURL(record.data);
video.src = blobUrl;
video.load();
video.play();
// 播放结束时清理(可选,也可在页面卸载时统一清理)
video.onended = () => URL.revokeObjectURL(blobUrl);
}
}
4. 注意事项与优化建议
实际使用中需关注几个关键点:
- 存储大小限制:IndexedDB 容量通常为磁盘空间的 50%~80%,但单次事务过大可能触发 QuotaExceededError;建议分块存储超大文件(如 >100MB 视频),或结合 Cache API + Service Worker 更适合流式资源
- 兼容性:所有现代浏览器均支持 Blob 存储,但旧版 Safari(≤12.1)对 large Blob 支持不稳定,可降级为 ArrayBuffer + typed array 处理
-
搜索与过滤:利用 index(如
byType)快速筛选媒体类型,避免全表扫描 -
更新策略:若需更新已存 Blob,仍用
put()覆盖同 key 记录即可,旧 Blob 会被自动回收
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










