IE 释放 blob url

Posted

技术标签:

【中文标题】IE 释放 blob url【英文标题】:IE frees blob urls 【发布时间】:2013-12-18 09:43:38 【问题描述】:

我有两个音频文件必须一个接一个地播放。 为此,我使用 XHR 下载了这两个文件

var xhr = new XMLHttpRequest();
xhr.open('GET', fileURL, true);
xhr.responseType = 'arraybuffer';

xhr.onload = function () 
  data = new Uint8Array(xhr.response);
  //... other handling code
;

并从它们构造一个 Blob

var blob = new Blob([data], type: 'video/mp4')

这些我用来构建 Blob URL

var url = URL.createObjectURL(blob)

然后注入<audio>标签。 (audioDOM.src = url;)

此过程适用于 Chrome 和 Firefox。但是 IE11 有时会给我一个问题,它显示以下通知:

通过关闭它们所针对的 blob 来撤销一个或多个 blob URL 被创造。这些 URL 将不再解析为数据支持 该 URL 已被释放。

然而,最奇怪的部分是它确实适用于第一个文件(在 IE 中),但不适用于第二个文件。它们都对整个过程使用相同的代码,只是使用不同的fileURL 来调用。这两个文件都存在,已正确下载并已记录到控制台进行验证。

我尝试在构建 blob 之前复制数据,但这似乎无关紧要:错误仍然存​​在。

有没有人知道是什么导致了问题以及如何解决?

在 sbgoran 之后编辑: 整个脚本在单个文档上运行,不会重新加载。我仍然很困惑为什么会这样。当音频无法加载时,我确实设法通过循环和创建新 URL 来创建解决方法,但这不是一个可行的解决方案。奇怪的是,上述方法随机失败:有时 URL 在加载到 <audio> 标记时可用,有时则不可用。

【问题讨论】:

您是否有理由不能将 src=whatever 和 onended=playsecond() 用于第一次或如下所示:***.com/questions/9326288 ?... 使用这样的 blob 似乎效率低下且不必要。跨度> 是的,我有充分的理由这样做。其中之一是在我的最终实现中,对原始两个文件中的数据进行了编辑以形成两个新文件。然而,这对失败率没有影响:我进行了测试,其中按照上述方式简单地复制了 blob,但问题仍然存在。 (所以操作对这里所说的问题没有影响) 【参考方案1】:

除了 sbgoran 的回答之外,我还有另一个可能的原因 - 作为discussed on WhatWG mailing list,IE 中存在一个错误,当指向它的变量超出范围时,它会导致 Blob 被垃圾收集 - 即使仍然存在对象指向尚未撤销的 Blob 的 URL。

解决方法可以依赖于在需要对象 URL 时保留变量中的原始 Blob 对象,然后使变量无效并随后撤销其对象 URL。

【讨论】:

+1:这听起来完全合理。我本来可以让Blob 在某个地方活着,只是出于良好的设计;该 URL “感觉”不像是对我的强烈引用。 听起来确实有道理。但是,经过测试,这似乎并不能解决问题。我将对 blob 和 uri 的引用都存储在一个数组中,但问题仍然存在。 我的错。这确实解决了问题。释放内存的时候记得先撤销object url,不然还是会出现提示。【参考方案2】:

基于MSDN createObjectURL method 页面的Remarks 部分,IE 可能会抱怨很多事情。我不确定您之前是否阅读过此 MSDN 页面,但也许它可以在某些方面有所帮助。

我会特别检查有关 blob url 来源政策的说明

Blob url 受制于原始策略。这意味着它们只能用于与运行创建 url 的脚本的文档具有相同来源的文档中。如果您需要使用在不同域中运行的 blob 对象,则必须使用 postMessage API 将 blob 数据发送到框架,然后在那里创建 blob: url。

createObjectURL 返回的 URL 在创建文档的生命周期内有效,

【讨论】:

是的,我已经知道了。如果加载音频失败,我确实设法通过重新创建 blob url 来解决问题,但我还没有找到可靠的解决方案。即使通知声称 blob 数据不可用,但情况并非如此:即使在发出通知后仍然可以访问 blob 数据。【参考方案3】:

然后注入到<audio>标签中。

你能给我这个代码吗?

也许 IE 有某种垃圾收集器,只要没有包含 blob url 的 DOMString 实例,它就会释放 blob url。

根据这个理论,使用innerhtml(可能还有 setAttribute ?)创建您的音频标签,我的意思是连接 url (foo.innerHTML = '<audio src="' + url + '" />';) 意味着唯一包含 blob url 的 DOMString(由URL.createObjectURL) 将在函数结束后的某个时间被垃圾收集。

【讨论】:

注入只是通过使用audioDOM.src = url; 发生的,所以应该不是问题

以上是关于IE 释放 blob url的主要内容,如果未能解决你的问题,请参考以下文章

关于iframe 关闭后,IE下不能释放内存的问题,跪求解决方案.

VB使用webbrowser控件时怎样释放内存?我使用了许多webbrowser数组时,只见占用内存越来越大。最后崩溃

通过 JGit 克隆 repo 后如何释放文件系统锁

HttpClient 4.0.1 - 如何释放连接? [复制]

关于mysql 删除数据后(.MYD,MYI)物理空间未释放

拖动页面元素,松开释放