web-dev-qa-db-fra.com

api filereader sur les gros fichiers

Mon code API de lecteur de fichiers a bien fonctionné jusqu’à ce qu’un jour, j’ai reçu un fichier txt de 280 Mo d’un de mes clients. La page se bloque juste dans Chrome et dans Firefox rien ne se passe. 

// 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") ); }}

Ce que j'essaie de faire ci-dessus, c'est d'obtenir le premier saut de ligne pour obtenir la longueur de colonne du fichier. Ne devrais-je pas le lire sous forme de texte? Comment obtenir la longueur de colonne du fichier sans casser la page sur les gros fichiers? 

31
ODelibalta

Votre application échoue pour les gros fichiers car vous lisez l'intégralité du fichier en mémoire avant de le traiter. Cette inefficacité peut être résolue en transmettant le fichier en continu (lecture de morceaux de petite taille), de sorte que vous ne devez conserver qu'une partie du fichier en mémoire.

Un objet File est également une instance de Blob, qui offre la méthode .slice pour créer une vue plus petite du fichier.

Voici un exemple supposant que l'entrée est ASCII (démo: 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);
    }
}

L'extrait précédent compte le nombre d'octets avant un saut de ligne. Compter le nombre de caractères dans un texte composé de caractères multi-octets est légèrement plus difficile, car vous devez tenir compte de la possibilité que le dernier octet du bloc puisse faire partie d'un caractère multi-octets.

55
Rob W

Il y a une bibliothèque géniale appelée Papa Parse qui le fait d'une manière gracieuse! Il peut vraiment gérer de gros fichiers et vous pouvez également utiliser WebWork.

Il suffit d’essayer les démos qu’ils fournissent: https://www.papaparse.com/demo

1
Edy Segura