javascript - 将 blob 作为分段上传会导致 500mb 后在 Chrome 上出现 net::ERR_FILE_NOT_FOUND

标签 javascript google-chrome upload blob multipartform-data

我只在 Google Chrome 和 Chromium 上遇到了一个非常奇怪的问题。

背景是:

我使用分段上传方法将文件上传到我的服务器,这意味着我将文件分成 10mb 的 block 并将每个 block 发送到服务器。这在具有任何大小文件的所有浏览器中都可以完美运行,当我需要加密每个 block 时问题就开始了。

对于加密,我使用 CryptoJS,在上传 block 之前,我对其进行加密并获取要上传的生成的 Blob,当我必须上传少于 50 个 block (50 个 blob)时,这在 Chrome 上运行良好,总共大约 500mb),之后我得到一个 POST http://(...) net::ERR_FILE_NOT_FOUND

奇怪的是,这适用于所有其他浏览器,包括现在基本上是 Chrome 的 Opera,除了 Chrome 和 Chromium。我在 IE、Firefox、Edge、Safari、Opera、Chrome 和 Chromium 上对其进行了测试。

下面您可以看到我的代码是如何工作的,所以你们可以有一个想法,这不是我在应用程序中使用的真实代码,而是我编写的测试代码,它产生了相同的结果。

我不是获取文件的切片 (File.slice),而是将其作为 block 上传并对其进行加密以获取 blob,我是将生成一个具有我的 block 大小的伪造 blob。我将 setTimeout 用于模拟加密 blob 所需的时间。正如我之前所说,通过这样做,我得到了与我的真实代码相同的结果:

function uploadNext(prevResponse) {  
    if (currentPart == totalPartsFile)
        return;

    //var chunk = getNextChunk();
    var totalSize = file.size;

    setTimeout(function() {
        var blob = new Blob([new ArrayBuffer(constants.chunkSize)], {
            type: 'application/octet-string',
            name: file.name
        });

        console.log(blob);

        blob.encrypted = true;
        blob.key = encryptionKey;
        blob.mimeType = file.mimeType;
        blob.name = file.name;
        blob.originalFileSize = originalFileSize || file.size;
        
        uploadFile(objectId, currentPart, blob, totalSize, prevResponse, function(resp) {
            uploadNext(resp);
        });
    }, 1000);
}

所以,上面的代码是生成我的 blob 的地方,下面是上传部分:

function uploadFile (objectId, index, blob, totalSize, prevResponse, callback) {

    var format = "encrypted";
    var params = "?format=" + format + (format === "encrypted" ? "&encoding=base64" : "");
    var endPoint = constants.contentServiceUrl + resourceService.availableResources.addContents.link.split(':objectId').join(objectId) + params;

    var formData = new FormData();

    formData.append("totalFileSizeBytes", totalSize);
    formData.append("partIndex", index);
    formData.append("partByteOffset", previousOffset);
    formData.append("chunkSize", blob.size);
    formData.append("totalParts", totalPartsFile);
    formData.append("filename", blob.name);

    if (currentPart != 0) {
        formData.append("uploadId", prevResponse.uploadId);
        formData.append("bucket", prevResponse.bucket);
    }

    if (finalChunk) {
        for (var key in etags1) {
            formData.append("etags[" + key + "]", etags1[key]);
        }
    }

    formData.append("data", blob);

    previousOffset += blob.size;

    var request = {
        method: 'POST',
        url: endPoint,
        data: formData,
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    }

    $http(request)
        .success(function(d) {
            _.extend(etags1, d.etags);
            console.log(d);
            callback(d);
        })
        .error(function(d) {
        console.log(d);
    });                                                
}

当然还有其他支持变量和代码我没有放在这里,但这足以让我们了解我们正在处理的内容。

在这个例子中,我使用的是 AngularJS 的 $http 模块,但我也尝试过使用纯 XMLHttpRequest,我得到了相同的结果。

就像我说的,我只得到 POST http://(...) net::ERR_FILE_NOT_FOUND 文件大于 499mb(50+ block )并且只在 Chrome 中。

我在此处发布此问题是因为我一直在寻找解决方案,但找不到与此问题相关的任何内容,我在互联网上找到的最接近的内容是 Chromium 项目论坛中的此问题:

https://code.google.com/p/chromium/issues/detail?id=375297

此时我真的不知道该怎么办了,所以我想知道过去是否有人遇到过类似的问题并能以某种方式解决它。

提前感谢您的回答。

最佳答案

chrome 只能为任何 blob 分配 500mb,所以如果你尝试分配 500mb + 1 字节,它显然会忽略该字节,要解决这个问题你将不得不以 499mb 的 block 读取文件然后你将不得不在服务器合并文件。

或者您可以尝试像 ZipJS 这样的东西,然后上传 zip,它对我有用。

    var zip = new JSZip();
    zip.file("file1", "content1");
    zip.file("file2", "content2");

关于javascript - 将 blob 作为分段上传会导致 500mb 后在 Chrome 上出现 net::ERR_FILE_NOT_FOUND,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34780926/

相关文章:

javascript - 页面重新加载时保存事件 <li>

javascript - AngularJS - 如何将 id 从嵌套的 ng-repeat 传递给 api

javascript - Windows下CURL发送参数

javascript - 使用 jquery val() 清除只读输入日期在 Firefox 上失败,在 Chrome 上成功。为什么?

Python Rest客户端api上传文件

javascript - 以 html post 形式存储重置密码 token 是否安全?

javascript - button_to 上的 remote true 不进行 ajax 调用

php - 为什么它在 chrome(仅在 Windows 上)和 firefox 中看起来不同我的样式规则?

file - 如何限制dropzone.js文件上传的数量?

Golang http.NewRequest 总是返回 404 - Postman ok