【问题标题】:javascript - locally generating and downloading a huge filejavascript - 本地生成和下载一个巨大的文件
【发布时间】:2015-10-23 11:36:50
【问题描述】:

我有以下用于下载文件的 JavaScript 代码,我不禁想我是从这里得到的:Create a file in memory for user to download, not through server

但是,这个函数在 Chrome 中崩溃了,因为我试图下载太多数据(它可能是几 MB,但对于 1 MB 以下的下载似乎可以正常工作。我还没有做很多指标)。

我真的很喜欢这个功能,因为它可以让我从现有的巨大 JavaScript 变量中创建一个字符串并立即下载它。

那么我的两个问题是:

A) 导致崩溃的原因是什么?是字符串text 的大小还是这个函数中有什么东西?我读到 60MB 的字符串在 JavaScript 中是可能的,但我认为我还没有达到。

B) 如果是这个功能,是否有另一种简单的方法来下载一些允许我通过 JavaScript 在本地生成内容的巨大文件?

function download(filename, text) {
  var element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
  element.setAttribute('download', filename);

  element.style.display = 'none';
  document.body.appendChild(element);
  element.click();
  document.body.removeChild(element);
}

【问题讨论】:

  • @GolezTrol 你知道 Chrome 什么时候给你那个小方脸,然后说“他死了吉姆!”或“哇!”随着页面背景变成深灰蓝色?
  • 啊,那种崩溃。 :)
  • "对于 1 MB 以下的下载似乎可以正常工作" -- 我来到这里希望为我的 2 GB 下载找到答案...
  • @JohnWeisz 在兔子洞里,我发现了这个:github.com/jimmywarting/StreamSaver.js 它可以帮助您在本地下载 Gigs 数据:)

标签: javascript file download


【解决方案1】:

它在其他浏览器中是否有效?尝试使用调试器并在函数内部设置一个断点并单步执行。

尝试通过创建一个包含您要设置为 href 的字符串的 var 来分解 element.setAttribute 和数据内容,这样您就可以看到更多的故障点。

查看encodeURIComponent 函数是否因大字符串而失败。

字符串在javascript中是不可变的,对于那些知道的人来说,这意味着它们的创建是最终的,你不能修改字符串,或者附加到一个字符串,你必须为每次更改创建一个新的。 encodeURIComponent 哪个 url 对字符串进行编码可能会根据字符串的内容进行数千次更改,从而转义 > 1mb 的字符串。即使您使用需要转义的零个字符,当您调用该函数并将其附加到 'data:text/plain;charset=utf-8,' 字符串时,它也会从这两个字符串中创建一个新字符串,从而有效地使该操作所需的内存增加一倍。

根据特定浏览器处理此功能的方式,它根本没有针对长字符串进行优化,因为大多数浏览器的 url 字符限制约为 2000 个字符(通常为 2048 个),那么浏览器中的实现很可能不是进行低级逃生。如果这个函数确实是罪魁祸首,你将不得不找到另一种方法来 uri 转义你的字符串。可能是库或自定义低级转义。

如果调试器显示这个函数不是问题,另一个明显的瓶颈是当你将这个巨大的链接附加到 dom 时,浏览器可能会冻结在那里试图处理这个命令,为此它可能需要一个下载问题的完全不同的解决方案。

虽然这只是猜测,但希望它能引导您朝着正确的方向前进。

【讨论】:

  • 谢谢 - 我将逐步介绍这个函数,看看它在什么时候中断(并在 cmets 中进行更新)。我认为必须有一个一致的断点,因为该功能工作相对较快,直到达到一定的数据量(并且网站继续工作,直到达到该数据量时按下下载按钮)。
  • 更新:崩溃实际上发生在element.click() 调用中。我想知道这是否是 URL 大小的问题。
  • 实际上正是如此 - 2MB 似乎是 chrome 中数据 URI 的限制,经过一些实验,我注意到我的崩溃时间约为 3MB。我将把你的答案标记为答案,因为它让我到了正确的位置,但也许添加它是因为 URI 的大小是问题所在。 stackoverflow.com/questions/695151/…
  • 好收获!我不会想到使用数据前缀会导致 URI 限制发挥作用,但它确实很有意义。
【解决方案2】:

虽然我将 Rickey 的答案标记为正确答案是因为它让我得到了正确答案,但我找到了一个解决方法:

JavaScript blob filename without link

由于 Chrome 对 URI 长度的限制,此链接上接受的答案能够处理超过 8MB,而数据 URI 能够处理 2MB。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多