Подтвердить что ты не робот

Filereader api для больших файлов

Мой код api для чтения файлов работает до сих пор, пока в один прекрасный день я не получил файл размером 280 МБ от одного из моих клиентов. Страница просто падает прямо в Chrome и в Firefox ничего не происходит.

// create new reader object 
var fileReader = new FileReader(); 

// read the file as text 
fileReader.readAsText( $files[i] );  
fileReader.onload = function(e) 
{   // read all the information about the file 
    // do sanity checks here etc... 
    $timeout( function() 
    {    
        // var fileContent = e.target.result;
        // get the first line 
        var firstLine = e.target.result.slice(0, e.target.result.indexOf("\n") ); }}

То, что я пытаюсь сделать выше, это получить первый разрыв строки, чтобы я мог получить длину столбца файла. Должен ли я не читать его как текст? Как я могу получить длину столбца файла, не разбивая страницу на большие файлы?

4b9b3361

Ответ 1

Ваше приложение не работает для больших файлов, потому что перед его обработкой вы читаете полный файл в памяти. Эта неэффективность может быть решена путем потоковой передачи файла (чтение фрагментов небольшого размера), поэтому вам нужно только сохранить часть файла в памяти.

A File object также является экземпляром Blob, который предлагает метод .slice для создания меньшего представления файла.

Вот пример, который предполагает, что вход ASCII (demo: http://jsfiddle.net/mw99v8d4/).

function findColumnLength(file, callback) {
    // 1 KB at a time, because we expect that the column will probably small.
    var CHUNK_SIZE = 1024;
    var offset = 0;
    var fr = new FileReader();
    fr.onload = function() {
        var view = new Uint8Array(fr.result);
        for (var i = 0; i < view.length; ++i) {
            if (view[i] === 10 || view[i] === 13) {
                // \n = 10 and \r = 13
                // column length = offset + position of \r or \n
                callback(offset + i);
                return;
            }
        }
        // \r or \n not found, continue seeking.
        offset += CHUNK_SIZE;
        seek();
    };
    fr.onerror = function() {
        // Cannot read file... Do something, e.g. assume column size = 0.
        callback(0);
    };
    seek();

    function seek() {
        if (offset >= file.size) {
            // No \r or \n found. The column size is equal to the full
            // file size
            callback(file.size);
            return;
        }
        var slice = file.slice(offset, offset + CHUNK_SIZE);
        fr.readAsArrayBuffer(slice);
    }
}

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