Извлечение частичных данных из ArrayBuffer FileReader

Я использую метод HTML5 FileReader readAsArrayBuffer() для чтения файла в память. Согласно спецификации (ссылка выше):

При обработке чтения по мере того, как данные из большого двоичного объекта становятся доступными, пользовательские агенты должны ставить в очередь задачи для обновления результата с частичными данными большого двоичного объекта в виде объекта ArrayBuffer [TypedArrays], содержащего байты, прочитанные до завершения чтения, чтобы сопровождать запуск событий прогресса. При получении атрибут результата возвращает частичные данные BLOB-объектов, представляющие количество загруженных в данный момент байтов (как долю от общего числа) [ProgressEvents] в виде объекта ArrayBuffer [TypedArrays]; пользовательские агенты должны возвращать по крайней мере один такой ArrayBuffer [TypedArrays] при обработке этого метода чтения. Последнее возвращаемое значение — по завершении чтения.

Однако в браузерах, которые я тестировал (Firefox, Chrome и Opera), свойство reader.result не обновлялось постоянно. Например:

var reader = new FileReader(), pos = 0;

reader.addEventListener("progress", function(event){
    console.log(reader.result);
    var content = new Uint8Array(reader.result, pos, event.loaded);
    pos = event.loaded;

    // do stuff with the content down here
});

document.getElementById("fileInput").addEventListener("change", function(event){
    reader.readAsArrayBuffer(event.target.files[0]);
});

где есть HTMLInputElement с идентификатором fileInput и типом file. Когда выбран достаточно большой файл и выполняется обратный вызов, вот что происходит в консоли (этот пример из Chrome):

null
Uncaught TypeError: Type error

Я считаю, что TypeError возникает из-за того, что представление массива Uint8Array не может прочитать фрагмент из ArrayBuffer, поскольку ArrayBuffer имеет значение null.

Как ни странно, если файл большой, но не слишком большой, несколько событий выполнения действительно будут успешно выполнены.

Как вы надежно реализуете ArrayBuffer FileReader, чтобы предоставить вам данные, которые вам нужны, при событии «прогресс»?


person sffc    schedule 23.05.2013    source источник


Ответы (1)


Я думаю, вы можете прочитать ArrayBuffer после загрузки файла. Следующая функция также позаботится о больших файлах. Надеюсь, поможет,

function onfilechange(evt) {
var reader = new FileReader(); 
reader.onload = function(evt) {
  var chars  = new Uint8Array(evt.target.result);
  var CHUNK_SIZE = 0x8000; 
  var index = 0;
  var length = chars.length;
  var result = '';
  var slice;
  while (index < length) {
    slice = chars.subarray(index, Math.min(index + CHUNK_SIZE, length)); 
    result += String.fromCharCode.apply(null, slice);
    index += CHUNK_SIZE;
  }
  // Here you have file content as Binary String in result var
};
reader.readAsArrayBuffer(evt.target.files[0]);
}
person Rohit Singh Sengar    schedule 03.09.2014