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
相关产品推荐
相关产品推荐

