You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js无服务端应用:刷新后如何复用localStorage存储的Blob URL?

问题原因

URL.createObjectURL()生成的Blob URL是浏览器内存中对应Blob的临时引用,页面刷新后,浏览器会回收该Blob占用的内存,存储在localStorage里的URL字符串自然失去关联,无法再指向有效资源。

解决方案

方案1:将视频转为Base64字符串存储(适合小体积视频)

把文件读取为Base64编码的字符串,直接存入localStorage,刷新后可以直接作为video的src使用。缺点是Base64会比原文件体积大30%左右,且受限于localStorage的5MB存储上限。

保存代码:

const reader = new FileReader();
reader.onload = (e) => {
  localStorage.setItem('videoBase64', e.target.result);
};
// 读取选中的视频文件为Base64
reader.readAsDataURL(data.file[0]);

读取代码:

const vidBase64 = localStorage.getItem('videoBase64');
if (vidBase64) {
  videoRef.current.src = vidBase64;
}

方案2:用IndexedDB存储Blob本身(适合大体积视频)

IndexedDB支持直接存储Blob类型数据,存储空间远大于localStorage(通常可达几百MB甚至更多),是存储大文件的理想方案。

保存代码:

function saveVideoToDB(blob) {
  const request = indexedDB.open('VideoStorage', 1);

  // 初始化数据库表
  request.onupgradeneeded = (e) => {
    const db = e.target.result;
    if (!db.objectStoreNames.contains('tempVideos')) {
      db.createObjectStore('tempVideos');
    }
  };

  request.onsuccess = (e) => {
    const db = e.target.result;
    const transaction = db.transaction('tempVideos', 'readwrite');
    const store = transaction.objectStore('tempVideos');
    // 存入Blob,键名设为'tempVideo'方便后续读取
    store.put(blob, 'tempVideo');
    transaction.oncomplete = () => db.close();
  };
}

// 获取到视频文件后调用
saveVideoToDB(data.file[0]);

读取代码:

function loadVideoFromDB(callback) {
  const request = indexedDB.open('VideoStorage', 1);

  request.onsuccess = (e) => {
    const db = e.target.result;
    const transaction = db.transaction('tempVideos', 'readonly');
    const store = transaction.objectStore('tempVideos');
    const getRequest = store.get('tempVideo');

    getRequest.onsuccess = () => {
      if (getRequest.result) {
        // 重新生成Blob URL
        const blobUrl = URL.createObjectURL(getRequest.result);
        callback(blobUrl);
      }
      db.close();
    };
  };
}

// 页面加载后读取并设置视频源
loadVideoFromDB((blobUrl) => {
  videoRef.current.src = blobUrl;
});

注意事项

  • 无论用哪种方案,当不再需要Blob URL时,记得调用URL.revokeObjectURL()释放内存,避免内存泄漏:
useEffect(() => {
  return () => {
    if (videoRef.current?.src) {
      URL.revokeObjectURL(videoRef.current.src);
    }
  };
}, []);
  • 如果仅需要在页面刷新后保留视频(不需要跨浏览器会话),可以考虑使用sessionStorage替代localStorage,但本质和Base64方案逻辑一致,只是存储有效期不同。

内容的提问来源于stack exchange,提问作者Quiet Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:22:26