在谷歌浏览器上下载大文件(最大 15 mb)时出现问题
Posted
技术标签:
【中文标题】在谷歌浏览器上下载大文件(最大 15 mb)时出现问题【英文标题】:Problems downloading big file(max 15 mb) on google chrome 【发布时间】:2016-12-11 10:34:05 【问题描述】:我在 Google Chrome 中遇到下载问题。 我正在使用 Ruby 2.2、Rails 4.2、AngularJS 1.2。
我们这里没有数据库。我们通过 API 获得的一切。我们尝试下载的文件大约是 7 mb。它给了我们“失败:网络错误”。虽然它在 Firefox 上运行良好。
我们从 API 获取 JSON 格式的二进制数据。我们正在解析它。然后:
send_data response_fields["attachment"], type: response_fields["mimeType"], disposition: 'attachment', filename: params[:filename]
当我们使用 AngularJS 时,我们在 AngularJS 控制器中捕获该值,然后将其转换为:
var str = data;
var uri = "data:" + mimeType + ";base64," + str;
var downloadLink = document.createElement("a");
downloadLink.href = uri;
downloadLink.download = filename;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
这适用于 Firefox 甚至 Chrome 以减小文件大小。不知道为什么它会在 Chrome 上显示更大尺寸的错误。
有什么建议吗?
谢谢。
【问题讨论】:
尝试使用 blob 代替 base64 我遇到同样的错误:下载失败-网络错误 【参考方案1】:这几乎是1 和2 这些问题的重复,但由于它们确实专门处理画布元素,我将在这里重写一个更全局的解决方案。
这个问题是由于 chrome 在锚点 (<a>
) download
属性中设置的大小限制。我不太确定他们为什么这样做,但解决方案很简单。
将您的 dataURI 转换为 Blob,然后从此 Blob 创建一个 ObjectURL,并将此 ObjectURL 作为锚点的下载属性传递。
// edited from https://developer.mozilla.org/en-US/docs/Web/API/htmlCanvasElement/toBlob#Polyfill
function dataURIToBlob(dataURI)
var binStr = atob(dataURI.split(',')[1]),
len = binStr.length,
arr = new Uint8Array(len),
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
for (var i = 0; i < len; i++)
arr[i] = binStr.charCodeAt(i);
return new Blob([arr],
type: mimeString
);
var dataURI_DL = function()
var dataURI = this.result;
var blob = dataURIToBlob(dataURI);
var url = URL.createObjectURL(blob);
var blobAnchor = document.getElementById('blob');
var dataURIAnchor = document.getElementById('dataURI');
blobAnchor.download = dataURIAnchor.download = 'yourFile.mp4';
blobAnchor.href = url;
dataURIAnchor.href = dataURI;
stat_.textContent = '';
blobAnchor.onclick = function()
requestAnimationFrame(function()
URL.revokeObjectURL(url);
)
;
;
// That may seem stupid, but for the sake of the example, we'll first convert a blob to a dataURI...
var start = function()
stat_.textContent = 'Please wait while loading...';
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function()
status.textContent = 'converting';
var fr = new FileReader();
fr.onload = dataURI_DL;
fr.readAsDataURL(this.response);
;
xhr.open('GET', 'https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4?dl=0');
xhr.send();
confirm_btn.parentNode.removeChild(confirm_btn);
;
confirm_btn.onclick = start;
<button id="confirm_btn">Start the loading of this 45Mb video</button>
<span id="stat_"></span>
<br>
<a id="blob">blob</a>
<a id="dataURI">dataURI</a>
还有一个用于 FF 的 jsfiddle version,因为它们不允许来自 stack-sn-ps 的 download
attribute...
【讨论】:
遗憾的是 chrome 将 URI 限制为 2MB ***.com/a/41755526/704008。将 blob 用于大尺寸的绝佳解决方法。 FF & chrome Fiddle 有什么区别?好像一样 @PranavSingh,是的,它们是相同的(IIRC)。只是FF用download
属性和stacksn-ps做了一些奇怪的事情(在我的身上,它没有显示下载弹出窗口,并用blob的名称保存,没有扩展名)但它实际上似乎在FF 52上修复了跨度>
@PranavSingh,你的意思不是在 jsfiddle 上也不是在你自己的页面上?这听起来像是开发版中的一个错误。无论如何,不要更改返回的 blobURI。仅应使用download
属性来设置文件名。对于更大的浏览器支持,您可能需要使用 FileSaver.js 库。您只需向它提供生成的 blob 和文件名,它将解决不同实现中的许多怪癖。 (也适用于我的 54 nightly,我没有开发版)
@Kaiido 我的意思是我有一个休息 API(POST),它可以动态创建和流式传输 zip 到客户端。如何在客户端/浏览器端使用它?我已经使用表单提交单击完成了此操作,但是对于非常大的文件,它会在一段时间后使网络失败。此外,这在服务器位于本地时工作正常,但在部署在 google k8s 上时会出现网络失败错误。在过去的 18-20 天里,我一直坚持这一点。以上是关于在谷歌浏览器上下载大文件(最大 15 mb)时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
谷歌浏览器点新链接时出现:此文件可能会损坏你的计算机。是啥问题?
怎么解决使用python的requests获得网页时出现sslEOFError错误