URL.createObjectURL() 和 FileReader.readAsDataURL() 的区别,大文件下载浏览器崩溃的处理方案


背景:大文件下载(2G以上)。研发和测试环境都没有问题,到现场大文件下载浏览器内存崩溃了。一开始使用 FileReader.readAsDataURL() 下载大文件会导致浏览器崩溃,使用URL.createObjectURL() 之后问题解决。

FileReader.readAsDataURL() 

URL.createObjectURL() 和 FileReader.readAsDataURL() 都是用于在浏览器中处理文件的方法,但它们有一些区别。

FileReader.readAsDataURL() 方法用于读取指定的文件,并将其内容转换为 Data URL 字符串。Data URL 是一种将文件内容嵌入到 URL 中的格式,可以直接用于在浏览器中显示文件内容。

let blob = new Blob([res.data]); // res.data是后台返回的文件

let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = (e) => {
    // 转换完成,创建一个a标签用于下载
    let a = document.createElement('a');
    a.download = fileName;
    a.href = e.target.result;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
}

以上的实现,下载大文件时,导致了浏览器的内存崩溃。 

URL.createObjectURL()

URL.createObjectURL() 方法用于创建一个指向指定文件的 URL。它接受一个参数,即要创建 URL 的文件对象(如 Blob 或 File 对象),然后返回一个表示该文件的 URL 字符串。这个 URL 可以被用于在浏览器中显示或处理文件,下面示例代码使用URL.createObjectURL()实现文件下载:

let blob = new Blob([res.data]); // res.data是后台返回的文件

let eleLink = document.createElement('a');
eleLink.download = fileName;
eleLink.style.display = 'none';

const url = URL.createObjectURL(blob);
// 将生成的url赋值给a标签的href属性
eleLink.href = url;
// 添加到dom节点body上
document.body.appendChild(eleLink);
// 触发点击
eleLink.click();
// 然后移除
document.body.removeChild(eleLink);
// 释放URL, 这样可以确保及时释放资源,避免内存泄漏问题。
URL.revokeObjectURL(url);

下载大文件时, FileReader.readAsDataURL()比较卡,URL.createObjectURL() 不卡,是为什么?

FileReader.readAsDataURL() 和 URL.createObjectURL() 是两种不同的方法,它们在处理大文件时的性能和效果可能会有所不同。

FileReader.readAsDataURL() 方法是将文件内容读取为 Data URL(Base64 编码的字符串)。这意味着它会将整个文件内容转换为一个非常长的字符串,这在处理大文件时可能会导致性能问题。因为将整个文件内容转换为 Data URL 需要耗费大量的内存和计算资源。

相比之下,URL.createObjectURL() 方法是为文件创建一个临时的 URL,可以直接访问文件内容。这个 URL 可以被用于加载文件,而不需要将整个文件转换为字符串。因此,URL.createObjectURL() 方法在处理大文件时可能更高效,因为它不需要将整个文件内容读取到内存中。

所以,如果你需要处理大文件并且关注性能,可以考虑使用 URL.createObjectURL() 方法来加载文件,而不是使用 FileReader.readAsDataURL() 方法。但是需要注意的是,使用 URL.createObjectURL() 方法创建的 URL 是临时的,使用完后需要及时释放,以避免内存泄漏。

将URL.createObjectURL(blob)赋值给dom属性,再移除掉这个dom,此时URL释放了嘛?

当你使用URL.createObjectURL(blob)创建一个URL,并将它赋值给DOM属性后,如果你移除了这个DOM元素,URL并不会立即释放。相反,URL会一直保持有效,直到你显式地调用URL.revokeObjectURL(url)来释放它。

调用URL.revokeObjectURL(url)会告诉浏览器该URL不再需要,浏览器会立即释放相关的资源。所以,如果你不再需要这个URL,记得在移除DOM元素后调用URL.revokeObjectURL(url)来释放它。这样可以确保及时释放资源,避免内存泄漏问题。

以下是一个示例代码,演示了如何使用URL.createObjectURL()和URL.revokeObjectURL():

// 创建URL
const url = URL.createObjectURL(blob);
// 将URL赋值给DOM属性
domElement.src = url;
// 移除DOM元素
domElement.remove();
// 释放URL
URL.revokeObjectURL(url);

 如果帮助到您了,可以留下一个赞👍告诉我  


文章作者: 程序猿小野
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 程序猿小野 !
评论