Chrome HTML5 FileReader аварийно завершает работу при попытке прочитать большой файл

У меня есть форма, которая позволяет пользователям выбирать zip-файл для загрузки. Я пытаюсь выполнить проверку этого zip-файла на стороне клиента перед его загрузкой на мой сервер, поскольку загрузка может занять некоторое время, и я также хотел бы сохранить пропускную способность.

Все, что мне нужно сделать, это прочитать файл .csv, который должен быть включен в zip, и проверить наличие других файлов в zip, на которые есть ссылки в .csv. Для этого я пытаюсь использовать JSZip.

Если архив небольшой, это прекрасно работает. Если архив большой (тестирование с файлом ~ 500 МБ), Chrome вылетает.

var  reader = new FileReader();
reader.onload = function (e) {
  console.log("Got here!");
  // Read csv using JSZip, validate zip contents
};
reader.readAsArrayBuffer(file);

В своем коде я закомментировал всю логику обратного вызова onload и убедился, что ни одна из них не вызывает сбоя. Я обнаружил, что Chrome дает сбой до того, как будет вызван обратный вызов onload.

Я проверил это в FireFox с гораздо большими zip-файлами, и все работает нормально.


person Danny    schedule 08.01.2014    source источник
comment
Какую версию хрома вы используете?   -  person Alon Gubkin    schedule 09.01.2014
comment
31.0.1650.63. Только что обнаружил, что FireFox падает в тот же момент для меня с файлами размером более ~ 1,5 ГБ.   -  person Danny    schedule 09.01.2014
comment
Вероятно, на вкладке браузера не хватает памяти. Почему вы читаете такие большие файлы на стороне клиента?   -  person Ray Nicholus    schedule 09.01.2014
comment
Я столкнулся с той же ошибкой с большим BLOB. Я обнаружил, что это недокументированная ошибка, и никто ничего с ней не делает.   -  person Michal    schedule 09.01.2014
comment
FileReaderSync и веб-воркер   -  person epascarello    schedule 09.01.2014
comment
@Michal Если вам известны незадокументированные ошибки, отправьте отчет об ошибке: cbrug.com/new   -  person Rob W    schedule 09.01.2014


Ответы (1)


Это вкладка браузера, на которой не хватает памяти.

Чтобы работать с таким большим файлом, вы должны загружать его фрагменты за один раз:

Используйте File.slice(start, end + 1), прочитайте полученное Blob как ArrayBuffer, поработайте над этим фрагментом, а затем убедитесь, что на него не осталось ссылок, чтобы его можно было удалить сборщиком мусора.

В зависимости от того, что вы делаете с куском, вам, возможно, придется даже установить тайм-аут, чтобы дать сборщику гаража дополнительное время, чтобы добраться до него. Обязательно протестируйте все браузеры, которые вы поддерживаете, так как некоторые из них могут потребовать больших тайм-аутов или меньших фрагментов. Также имейте в виду, что сборка мусора может занять еще больше времени на перегруженных менее мощных компьютерах.

Это хороший пример нарезки. Конечно, вы бы нарезали на более крупные части. Вы также, вероятно, захотите объединить его со следующим примером на странице, чтобы дать отзыв о ходе выполнения, который включает в себя выборку фрагмента из медленного/удаленного хранилища в дополнение к текущему номеру фрагмента.

person Mihail Malostanidis    schedule 03.10.2017
comment
Ссылка, кажется, изменилась, на этой странице ничего не говорится о загрузке файлов в виде фрагментов, заранее спасибо - person maroof shittu; 30.05.2021
comment
@maroofshittu сумасшедший, как html5rocks.com/en/tutorials/file /dndfiles/#toc-slicing-files теперь перенаправляет на web.dev/read-files ! - person Mihail Malostanidis; 30.05.2021
comment
Тем не менее, ответ, вероятно, следует обновить, поскольку новый Blob.stream() , вероятно, намного лучше, чем Blob.slice() для этого варианта использования! - person Mihail Malostanidis; 30.05.2021