【问题标题】:How long does a Blob persist?Blob 会持续多久?
【发布时间】:2012-12-07 14:52:36
【问题描述】:

我正在尝试编写一个故障安全程序,该程序使用画布绘制非常大的图像(60 MB 可能是上限,而 10 MB 是下限)。我很早就发现调用画布的同步函数toDataURL通常会导致页面在浏览器中崩溃,所以我对程序进行了调整,使用了toBlob的方法,使用了一个填充器来实现跨浏览器的兼容性。我的问题是:使用URL.createObjectURL(blob) 方法的 Blob URL 能持续多久?

我想知道是否有一种方法可以缓存 Blob URL,以使其能够在浏览器会话之后持续存在,以防有人想在某一时刻渲染图像的一部分,关闭浏览器,然后返回并完成稍后通过再次将 Blob URL 读入画布并从它停止的点恢复。我注意到this optional autoRevoke argument 可能是我正在寻找的东西,但我想确认我正在尝试做的事情实际上是可能的。除非涉及不同的解决方案,否则您的答案中不需要代码示例,如果可以使用此方法或其他方法使 Blob URL 在会话之外持续存在,我只需要一个是或否。 (如果由于某种原因页面崩溃并且它也像“恢复会话”选项一样,这也会很方便。)

我在想这样的事情:

function saveCache() {
  var canvas = $("#canvas")[0];
  canvas.toBlob(function (blob) {
    /*if I understand correctly, this prevents it from unloading
      automatically after one asynchronous callback*/
    var blobURL = URL.createObjectURL(blob, {autoRevoke: false});
    localStorage.setItem("cache", blobURL);
  });
}

//assume that this might be a new browser session

function loadCache() {
  var url = localStorage.getItem("cache");
  if(typeof url=="string") {
    var img = new Image();
    img.onload = function () {
      $("#canvas")[0].getContext("2d").drawImage(img, 0, 0);
      //clear cache since it takes up a LOT unused of memory
      URL.revokeObjectURL(url);
      //remove reference to deleted cache
      localStorage.removeItem("cache");
      init(true); //cache successfully loaded, resume where it left off
    };
    img.onprogress = function (e) {
      //update progress bar
    };
    img.onerror = loadFailed; //notify user of failure
    img.src = url;
  } else {
    init(false); //nothing was cached, so start normally
  }
}

请注意,我不确定这是否会按照我的意图进行,所以任何确认都会很棒。

EDIT 刚刚意识到sessionStoragelocalStorage 不同:P

【问题讨论】:

  • 我刚刚测试了这段代码是什么,刷新页面时它似乎可以工作,但是当会话关闭时,localStorage 仍然存在,但 blobURL 没有......
  • Patrick,当您离开,然后点击返回按钮时会发生什么?
  • 与刷新页面时相同,因为它仍然是同一个会话。
  • 嗨@PatrickRoberts,我有一个问题:stackoverflow.com/questions/67015438/…

标签: javascript blob persistent-storage


【解决方案1】:

Blob URL 可以跨会话持续存在吗?不是你想要的方式。

URL 是一个表示为字符串的引用,您可以像任何字符串一样将其保存在 localStorage 中。 URL 指向的位置是您真正想要的位置,并且不会在会话中持续存在。

将 URL.toObjectUrl() 与 autoRevoke 参数结合使用时,URL 将持续存在,直到您调用 revokeObjectUrl 或“直到执行卸载文档清理步骤”。 (此处概述的步骤:http://www.w3.org/TR/html51/browsers.html#unloading-document-cleanup-steps

我的猜测是这些步骤是在浏览器会话到期时执行的,这就是为什么您的blobURL 的目标无法在后续会话中访问。

关于此的其他一些讨论:How to save the window.URL.createObjectURL() result for future use?

以上建议使用 FileSystem API 来保存画布元素的 blob 表示。第一次请求文件系统时,您需要请求 PERSISTENT 存储,并且用户必须同意让您将数据永久存储在他们的机器上。

http://www.html5rocks.com/en/tutorials/file/filesystem/ 有一本很好的入门书,你需要的一切。

【讨论】:

  • 那些文档清理步骤似乎发生在每个文档卸载上,这远在会话到期之前。
  • @Bergi 这就是我阅读文档时的想法,但根据 Patrick 的说法,刷新页面时它会起作用。我的猜测是,现代浏览器会阻止这些卸载步骤,直到窗口卸载(也许这就是 CTR+ALT+T 背后的原因使最后一个关闭的标签页恢复得这么好?)。
  • 看起来它取决于Browsing Context 来确定何时卸载特定的Document 已卸载(除非用户强制它):w3.org/TR/html51/…
  • 是的,我确信有优化;特别是对于快速页面重新加载。但这并不意味着您不应该依赖它们来工作:-)
  • 我同意。进一步研究,该规范要求用​​户代理在页面导航时执行这些步骤。我首先认为这些信息可以作为与浏览上下文历史相关的选项状态对象的一部分保存。它可能在那里,但文件 API 规范明确指出用户代理必须在卸载时撤销 URL。我无法找到有关在卸载方面如何处理刷新的参考资料。可能是调用了提示卸载,而不是随后的卸载。
猜你喜欢
  • 2011-04-06
  • 2014-05-21
  • 2021-02-09
  • 2011-10-05
  • 1970-01-01
  • 2011-09-11
  • 2018-10-28
  • 1970-01-01
  • 2016-02-26
相关资源
最近更新 更多