Загрузка блобов в качестве загрузки нескольких частей вызывает сеть:: ERR_FILE_NOT_FOUND в Chrome после 500 МБ
У меня очень странная проблема только в Google Chrome и Chromium.
Фон:
Я загружаю файлы на свой сервер, используя метод многофакторной загрузки, что означает, что я разбиваю файлы на куски размером 10 МБ и отправляю каждый фрагмент на сервер. Это работает безупречно во всех браузерах с файлами любого размера, проблема началась, когда мне нужно было зашифровать каждый фрагмент.
Для шифрования я использую CryptoJS, и, прежде чем загружать кусок, я зашифровываю его и получаю результирующий Blob
для загрузки, это отлично работает в Chrome, когда я загружаю менее 50 кусков (50 капотов, всего 500 мб), после чего я получаю a POST http://(...) net::ERR_FILE_NOT_FOUND
.
Как ни странно, это работает во всех других браузерах, включая Opera, которая в настоящее время является в основном Chrome, за исключением Chrome и Chromium. Я тестировал его на IE, Firefox, Edge, Safari, Opera, Chrome и Chromium.
Ниже вы можете увидеть, как работает мой код, чтобы вы, ребята, могли подумать, что это не настоящий код, который я использую в приложении, а скорее это тестовый код, который я написал, который дает тот же результат.
Вместо того, чтобы получать фрагмент (File.slice
) файла, который я собираюсь загрузить как кусок и зашифровать его, чтобы получить Blob
, я собираюсь создать поддельный 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+ кусков) и только в Chrome.
Я размещаю это здесь, поскольку искал решение, но я не мог найти ничего, связанного с этой проблемой, ближайшая вещь, которую я нашел в Интернете, была эта проблема на форуме проекта Chromium:
https://code.google.com/p/chromium/issues/detail?id=375297
В этот момент я действительно не знаю, что делать дальше, поэтому я хотел бы знать, имел ли кто-нибудь подобную проблему в прошлом и каким-то образом мог ее исправить.
Спасибо за ответы заранее.
Ответы
Ответ 1
Хром может выделять только 500 МБ для любого blob, поэтому, если вы попытаетесь выделить 500 Мбайт + 1 байт, он будет явно игнорировать этот байт, чтобы решить эту проблему, вам придется читать файл в кусках 499mb, а затем вам придется объединить файл на сервере.
Или вы можете попробовать что-то вроде ZipJS, а затем загрузить zip, это сработало для меня.
var zip = new JSZip();
zip.file("file1", "content1");
zip.file("file2", "content2");
Ответ 2
В последних исходных файлах хрома я обнаружил пределы blob.
-
ChromeOS:
- Рам - 20%
- Диск - 50% Примечание. Диск является пользовательским разделом, поэтому операционная система все еще может функционировать, если она заполнена.
-
Android:
- Desktop:
- Рам - 20% или 2 ГБ, если x64.
- Диск - 10%
ссылка хрома репо: https://cs.chromium.org/chromium/src/storage/browser/blob/blob_memory_controller.cc?l=63
Ответ 3
Кажется, это проблема с Firebug. Попытайтесь отключить его. Это работает для меня.
браузер Firefox. У меня возникла проблема, когда я загружал файл кусками. Я отключил плагины и утечку памяти не появляется. Возможно, это поможет вам
Для Chrome все работает нормально.