通过ajax调用下载大文件会在Chrome浏览器中显示"网络错误"

vic*_*tor 9 javascript ajax google-chrome

所以我试图下载一个带有ajax调用的zip文件到我的api.api以base 64编码的字节数组响应.现在对于大多数下载来说这很好用,但是当zip文件太大时,Chrome开始失败.适用于所有其他浏览器.从我在堆栈溢出中发现的,这是chrome中的一个已知问题,人们建议使用blob.事情是我使用blob仍然有问题.这是我处理下载的代码.我通过传入contentType的不同值来使用它来下载pdf和zip文件.有没有人遇到过这个问题?是否有任何可以添加到页面的工作或脚本可以解决此问题?

// data is base 64 encoded byte array
function download(data, filename, contentType) {

    var byteCharacters = atob(data);
    var byteNumbers = new Array(byteCharacters.length);
    for (var i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
    }
    var byteArray = new Uint8Array(byteNumbers);
    var blob = new Blob([byteArray], { type: contentType });

    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        // IE / edge workaround
        window.navigator.msSaveOrOpenBlob(blob, filename);
    } else if (navigator.userAgent.indexOf("Firefox") > 0) {
        var a = window.document.createElement('a');
        a.download = filename;
        a.style.cssText = "display: none";
        a.target = "_blank";
        // Append anchor to body.
        document.body.appendChild(a);
        a.href = "data:" + contentType + ";base64," + data;
        a.click();

        // Remove anchor from body
        document.body.removeChild(a);
    } else //Chrome, safari, etc
        {
            var a = document.createElement("a");
            a.style = "display: none";
            var url = window.URL.createObjectURL(blob);
            a.href = url;
            a.download = filename;
            a.click();
            window.URL.revokeObjectURL(url);
        }
}
Run Code Online (Sandbox Code Playgroud)

Wit*_*alt 5

API 使用 Base 64 编码的字节数组进行响应

为什么?我建议您添加一个方法来响应纯二进制 zip 文件。

设置后xhr.responseType = "blob";,只需保存它,就像在 Chrome 中一样。

如果你想保持 api 不变,请尝试摆脱 Array 并直接填充 Uint8Array。

联合发展署。我在 Ubuntu 18.04 和 16gb RAM 下的 Chrome 69 上对此进行了测试,我发现 Chrome 不会让我以这种方式下载超过 1000 MB 的数据。

您尝试下载的文件有多大?

自己检查一下(不要忘记确保没有任何东西会阻止下载):

function getBlob(size) {
    let u8a = new Uint8Array(size);
    for (var i = 0; i < size; i++) {
        u8a[i] = 33 + Math.floor(Math.random() * 5)
    }
    return new Blob([u8a]);
}

function downloadFile(source, filename) {
	if (source instanceof (File, Blob)) {
		filename = source.name || filename;
		source = URL.createObjectURL(source);
	}
	let link = document.createElement("a");
	link.style.display = "none";
	link.href = source;
	link.download = filename || "blob.bin";

	document.body.appendChild(link);

	link.click();

	setTimeout(function () {
		document.body.removeChild(link);

		URL.revokeObjectURL(source);
	}, 3000);
}
Run Code Online (Sandbox Code Playgroud)
Size (MB): <input id="in" type=number min=1 max=3000>
<button onclick="downloadFile(getBlob(1024*1024*(+document.getElementById('in').value)))">download</button>
Run Code Online (Sandbox Code Playgroud)