Chrome中消失blob的神秘案例(在IndexedDB中)

aca*_*lon 7 javascript google-chrome indexeddb

摘要

我想要做的很简单:

  • 1A.如果图像不是某种类型的本地存储(例如IndexedDB),则从服务器读取图像作为字节数组,放入本地存储(作为字节数组或对文件的引用,我不在乎)
  • 1B.如果映像在本地存储中,请从本地存储中读取字节数组.将此字节数组显示为html页面中的图像.

不知何故,在Blob,objectURL,indexedDB和缓存之间它都变得过于复杂并且表现出一些奇怪的行为.如果有一种方法可以将ArrayBuffer直接粘贴到图像中而不是首先转换为Blob然后转换为ObjectURL,那么我可能会使用它,因为它更简单并且摆脱了有问题的Blob和一些不必要的步骤.

如果您想查看流程的代码示例,请查看此jsfiddle.请注意,如下所述,jsfiddle示例中不会出现问题(由于某些原因我无法弄清楚).

我有一个原因是我使用的是IndexedDB,而不是依赖于浏览器缓存,所以让我们尽量避免这种讨论,并且与IndexedDB似乎在Chrome上行为不端的事实无关.

我感兴趣的是,如果有其他人遇到类似的问题或任何建议,如何改善这种情况.

细节

Chrome版本38.0.2125.104 m.

基本上,流程是通过索引检查blob是否在IndexedDB中(请参阅jsfiddle以供参考):

  • 1A.如果不是,则从server(xhr.open)检索blob ,将blob放入IndexedDB(objectStore.put)并显示blob(imgSrc = createTheObjectUrl(blob)).
  • 1B.如果是,则从IndexedDB(objectStore.get)中检索blob ,从blob创建URL,将image src设置为URL.

问题是它最初是有效的,但过了一会儿(有时当我刷新页面时,有时当我关闭Chrome并返回到网页时)我在访问blob的URL时得到404(未找到).

有几点需要注意: -

  1. 在我与其他浏览器的有限测试中,我没有看到相同的行为 - 其他浏览器似乎工作正常.
  2. 当我查看blob-internals页面(chrome:// blob-internals)时,我的磁盘上有一个blob的路径.当它工作时(图像可见),该文件存在,当它开始失败(404 Not Found)时该文件不存在(即使blob-internals仍然引用它).
  3. 当我试图在jsfiddle中重现这个问题时,问题不会发生.这是我的代码中的剪切和粘贴.不幸的是,我没有这个Web服务器的公共版本,所以我无法证明它失败了.

鉴于jsfiddle似乎总是有效,我能想到的是我的服务器配置方式有所不同.我看一下返回的标题的区别,我可以看到在jsfiddle的情况下,启用了缓存.所以,我开始认为这与缓存有关(这可能是一个完全错误的假设).好像Chrome正在跟踪blob的使用情况并将其从文件系统中删除,因为它会超出范围,从而导致IndexedDB中没有文件的条目(这本身就像一个bug).我不想在服务器上启用缓存,也不希望blob的生命周期依赖于服务器缓存设置.

解决方法

作为一种解决方法,我做了以下几点: -

  • 1A.如果映像不在IndexedDB中,则从服务器将其检索为Blob.将Blob转换为ArrayBuffer.将IndexedDB存储为ArrayBuffer.
  • 1B.如果图像在IndexedDB中然后检索,将ArrayBuffer转换为Blob,从Blob创建URL,将image src设置为URL.

这并不理想,因为这意味着我在第一次显示图像时(在它存储在IndexedDB中之前)从blob读取arraybuffer的额外开销,然后我从IndexedDB检索时将ArrayBuffer读入blob的开销很大.也许有一些聪明的共享资源正在进行,这意味着它们使用相同的底层缓冲区,但这意味着依赖于性能的实现.

还有更多 - 如果我从Blob创建一个由Blob创建的Blob,或者从Blob创建一个ArrayBuffer,那么来自ArrayBuffer的新Blob仍然不起作用.就好像使用某种共享引用计数资源一样.那就是 - 我能想到的任何解决方法都涉及在IndexedDB中存储blob不起作用.

mei*_*irm 2

似乎是 Chrome 中的错误,请参阅: https://code.google.com/p/chromium/issues/detail ?id=108012#c162

chrome canary 不会受此影响