Safari加载Blob到图片报WebKitBlobResource error 1如何解决?
故障原因
你遇到的WebKitBlobResource error 1是Safari内核的特有实现问题,核心原因如下:
- Blob对象本身是浏览器对二进制数据的临时引用,Chrome浏览器会将Blob对应的实际二进制内容和IndexedDB(LocalForage的默认存储后端)的记录一起持久化存储,刷新或重启浏览器后仍然可以正常读取。
- Safari的WebKit内核没有实现Blob的跨会话持久化:你直接将Blob存入LocalForage时,Safari仅存储了Blob的临时内部标识,没有写入实际二进制内容。页面刷新、浏览器重启后,原有临时标识对应的二进制数据已经被内核清理,读取到的Blob是无效对象,调用
createObjectURL时就会触发报错。
解决方案
有两种经过验证的兼容方案可以解决这个问题:
方案1:转Base64存储(兼容性最好)
把Blob转换为Base64格式的DataURL字符串后再存储,使用时直接赋值给图片src即可,不需要调用
createObjectURL,完全规避Blob持久化的兼容问题。
存储代码修改:canvas.toBlob(function(blob){ const reader = new FileReader(); reader.onloadend = function() { // 读取得到Base64格式的图片数据 const base64Img = reader.result; allItems.push({"string":string,"imageData":base64Img}); localforage.setItem("savedItems",allItems); } reader.readAsDataURL(blob); },"image/jpeg",0.02);读取使用代码修改:
// 直接赋值给图片src即可渲染 img.src = allItems[k]['imageData'];该方案仅存在一个微小劣势:Base64编码会让数据体积比原始二进制大33%左右,常规图片存储场景下几乎感知不到影响。
方案2:转ArrayBuffer存储(存储效率更高)
ArrayBuffer是纯粹的二进制数据结构,Safari对IndexedDB存储ArrayBuffer的持久化支持是正常的,读取后再转回Blob使用即可,不会有体积膨胀问题。
存储代码修改:canvas.toBlob(async function(blob){ // 把Blob内容转成ArrayBuffer const imgBuffer = await blob.arrayBuffer(); allItems.push({ "string":string, "imageBuffer":imgBuffer, "mimeType": blob.type }); localforage.setItem("savedItems",allItems); },"image/jpeg",0.02);读取使用代码修改:
// 把ArrayBuffer转回Blob const blob = new Blob([allItems[k]['imageBuffer']], {type: allItems[k]['mimeType']}); const url = URL.createObjectURL(blob); img.src = url; // 图片加载完成后主动释放对象URL,避免内存泄漏 img.onload = () => URL.revokeObjectURL(url);
额外注意事项
无论使用哪种方案,只要用到了createObjectURL生成临时地址,都要记得在使用完成后调用URL.revokeObjectURL(url)主动释放资源,Safari对未释放的临时资源清理逻辑更激进,累积过多也容易触发资源加载异常。
内容的提问来源于stack exchange,提问作者user1763510
相关产品推荐
相关产品推荐

