Chrome, FileReader API, event.target.result === "" - PullRequest
0 голосов
/ 17 апреля 2020

У меня есть веб-приложение, которое обрабатывает большие текстовые файлы (> 500 МБ) через FileReader. Использование readAsText. Работает отлично в течение многих лет, но внезапно я получаю пустой ответ. Event.target.result - пустая строка. 369mb работает. 589mb не работает. Я тестировал на нескольких компьютерах. Тот же результат.

Работает в FireFox.

Chrome, должно быть, представил это в недавнем обновлении.

Была ли отправлена ​​эта ошибка?

Есть ли обходной путь?

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

Это ограничение v8 для длины строки.

Была ли эта ошибка отправлена?

Ответственный коммит: https://github.com/v8/v8/commit/ea56bf5513d0cbd2a35a9035c5c2996272b8b728

Запустив пополам, я почувствовал на этот журнал изменений и обнаружил, что он был применен на Chrome v79.

До того, как это ограничение на 64-битных платформах было установлено равным 1024 МБ, новое ограничение составляет 512 МБ, половина.

Это означает, что затрагивается не только FileReader, но и любой метод, который попытается для создания такой большой строки.

Вот простой пример:

const header = 24;
const bytes = new Uint8Array( (512 * 1024 * 1024) - header );
let txt = new TextDecoder().decode( bytes );
console.log( txt.length ); // 536870888
txt += "f"; // RangeError

Есть ли обходной путь?

Единственный способ решить эту проблему - это обработать ваш текст кусками.

К счастью, вы имеете дело с данными ASCII, поэтому вы можете легко разделить свой ресурс и работать с этим чанком, используя метод Blob.slice():

// working in a Web-Worker to not freeze the tab while generating the data
const worker_script = `
(async () => {

  postMessage( 'Generating file, may take some time...' );

  const bytes = Uint8Array.from(
    { length: 800 * 1024 * 1024 },
    (_, i) => (i % 25) + 65
  );
  const blob = new Blob( [ bytes ] );

  const length = blob.size;
  const chunk_size = 128 * 1024 * 1024;

  postMessage( 'Original file size: ' + length );
  
  let As = 0;
  let i = 0;
  while ( i < length ) {
    const str = await blob.slice( i, i + chunk_size ).text();
    i += chunk_size;
    As += str.split( 'A' ).length - 1;
  }
  postMessage( 'found ' + As + ' "A"s in the whole file' );

} )();
`;
const worker_blob = new Blob( [ worker_script ] );
const worker = new Worker( URL.createObjectURL( worker_blob ) );
worker.onmessage = (evt) => console.log( evt.data );

Те, кто работает с форматированным текстом, таким как UTF-8, должны будут работать с многобайтовыми символами, и это может быть не так просто ...

Также обратите внимание, что даже в браузерах, которые позволяют генерировать такие большие строки, вы вполне можете столкнуться и с другими проблемами. Например, в Safari вы можете генерировать строки большего размера, но если вы сохраняете их слишком долго в памяти, браузер автоматически перезагрузит вашу страницу.

0 голосов
/ 20 апреля 2020

Как недавно? Вы проверяли это в других браузерах? Недавние проблемы, связанные с размером и скоростью, могут быть связаны с мерами, принятыми некоторыми поставщиками, в связи с вирусом SARS-CoV-2 и вызванным им ростом использования rnet.

A ограничение, например 384 МБ, может быть ограничением «одного размера пакета» в этом случае?

например https://www.vxchnge.com/blog/bandwidth-covid19

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...