Chrome 问题下载大文件(最大15 MB)在谷歌浏览器

lf3rwulv  于 2023-03-06  发布在  Go
关注(0)|答案(2)|浏览(1010)

我在谷歌浏览器下载时遇到了问题。我使用的是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 Controller中捕获该值,然后将其转换为:

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中较大的文件大小会出现错误。
有什么建议吗?
谢谢。

mu0hgdu0

mu0hgdu01#

这几乎是12这两个问题的翻版,但由于它们确实专门处理canvas元素,因此我将在这里重写一个更全局化的解决方案。
这个问题是由于chrome在anchor(<a>download属性中设置了一个大小限制,我不太清楚他们为什么这么做,但是解决方法很简单。
将dataURI转换为Blob,然后从此Blob创建ObjectURL,并将此ObjectURL作为锚的download属性传递。

// 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>

和一个jsfiddle version的FF,因为他们不允许download属性从堆栈片段...

vsaztqbk

vsaztqbk2#

这个答案更具体地回答了这个问题:[对于大文件,使用dataURI创建iframe失败,是否有解决方法?](Creating iframe with dataURI fails for large files, any workaround?
但是,该问题被标记为与此问题重复(实际上不是重复),之前的答案没有直接解决此问题。如果有此问题的好答案,将对我有所帮助。我能够提出此问题的解决方案,并将其复制如下。
下面是一个示例函数,它将接受dataURI,将其转换为blob并在iframe中打开它。

function dataURIToiFrame(dataURI) {

        function dataURIToBlob(dataURI) {

            let binStr = window.atob(dataURI.split(',')[1]),
              len = binStr.length,
              arr = new Uint8Array(len),
              mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

            for (let i = 0; i < len; i++) {
              arr[i] = binStr.charCodeAt(i);
            }

            return new Blob([arr], {
              type: mimeString
            });

          }

        let iframe = document.getElementById("iframe1");
        if (!iframe) {
            $("body").append(`
<a id="iframe1_wrapper" href="javascript:$('#iframe1_wrapper').remove();" style="position:absolute;right:0; top:50px; bottom:0; height:calc(100vh - 60px); width:650px; padding:20px;">
    <iframe id="iframe1" style="position: absolute;height:calc(100vh - 60px); width:650px; padding:0px;"></iframe><span style="position: relative; color: white;left: 10px">x</span>
</a>`);
            iframe = document.getElementById("iframe1");
        }

        iframe.src = URL.createObjectURL(dataURIToBlob(dataURI));       
}

相关问题