Utilisation De FileReader.readAsArrayBuffer () sur les fichiers modifiés dans Firefox

j'ai un problème avec FileReader.readAsArrayBuffer cela ne semble affecter que Firefox (j'ai testé dans la version actuelle - v40). Je ne sais pas si je fais quelque chose de mal ou si C'est un virus Firefox.

j'ai du JavaScript qui utilise readAsArrayBuffer pour lire un fichier spécifié dans un <input> champ. Dans des circonstances normales, tout fonctionne correctement. Toutefois, si l'utilisateur modifie le fichier après l'avoir sélectionné dans le <input> champ readAsArrayBuffer peut devenir très confus.

ArrayBuffer je serai de retour à partir de readAsArrayBuffer a toujours la longueur que le fichier était à l'origine. Si l'utilisateur change le fichier pour le rendre plus grand, Je ne reçois aucun Byte après la taille d'origine. Si l'utilisateur change le fichier pour le rendre plus petit, le buffer est toujours de la même taille et le 'surplus' dans le buffer est rempli avec les codes de caractères 90 (lettre majuscule 'Z' si considéré comme une chaîne de caractères).

puisque ce code est si simple et fonctionne parfaitement dans tous les autres navigateur j'ai testé, je pense que C'est un problème de Firefox. J'ai signalé comme un bogue à Firefox mais je veux m'assurer que ce n'est pas juste quelque chose d'évident que je fais mal.

Le problème peut être reproduit par l'extrait de code suivant. Tout ce que vous avez à faire c'est:

  1. rechercher un fichier texte qui comporte 10 caractères (10 n'est pas un nombre magique - je suis juste en utilisant un exemple)
  2. Observer que le résultat est un tableau de 10 éléments représentant les codes de caractères de chaque élément
  3. pendant que ceci est encore en cours d'exécution, supprimez 5 caractères du fichier et sauvez
  4. observez que le résultat est toujours un tableau de 10 éléments - les 5 premiers sont corrects mais les 5 derniers sont tous 90 (lettre majuscule Z)
  5. maintenant Ajouté 10 caractères (donc le fichier est maintenant 15 caractères de long)
  6. observez que le résultat est toujours un tableau de 10 éléments - les 5 derniers ne sont pas retourné

function ReadFile() {
  var input = document.getElementsByTagName("input")[0];
  var output = document.getElementsByTagName("textarea")[0];

  if (input.files.length === 0) {
    output.value = 'No file selected';
    window.setTimeout(ReadFile, 1000);
    return;
  }

  var fr = new FileReader();
  fr.onload = function() {
    var data = fr.result;
    var array = new Int8Array(data);
    output.value = JSON.stringify(array, null, '  ');
    window.setTimeout(ReadFile, 1000);
  };
  fr.readAsArrayBuffer(input.files[0]);

  //These two methods work correctly
  //fr.readAsText(input.files[0]);
  //fr.readAsBinaryString(input.files[0]);
}

ReadFile();
<input type="file" />
<br/>
<textarea cols="80" rows="10"></textarea>

Dans le cas de l'extrait de code ne fonctionne pas, l'exemple de code est également disponible comme un JSFiddle ici: https://jsfiddle.net/Lv5y9m2u/

18
demandé sur Stephen McDaniel 2015-08-26 02:07:38

2 réponses

intéressant, on dirait que FF cache la taille du tampon même si le fichier est modifié.

vous pouvez vous référer à ce lien, remplacé readAsArrayBuffer par une fonctionnalité personnalisée qui utilise readAsBinaryString. son bon fonctionnement en FF et chrome

function ReadFile() {
var input = document.getElementsByTagName("input")[0];
var output = document.getElementsByTagName("textarea")[0];

if (input.files.length === 0) {
    output.value = 'No file selected';
    window.setTimeout(ReadFile, 1000);
    return;
}

var fr = new FileReader();
fr.onload = function () {
    var data = fr.result;
    var array = new Int8Array(data);
    output.value = JSON.stringify(array, null, '  ');
    window.setTimeout(ReadFile, 1000);
};
fr.readAsArrayBuffer(input.files[0]);



//These two methods work correctly
//fr.readAsText(input.files[0]);
//fr.readAsBinaryString(input.files[0]);
}
if (FileReader.prototype.readAsArrayBuffer && FileReader.prototype.readAsBinaryString) {
    FileReader.prototype.readAsArrayBuffer = function readAsArrayBuffer () {
        this.readAsBinaryString.apply(this, arguments);
        this.__defineGetter__('resultString', this.__lookupGetter__('result'));
        this.__defineGetter__('result', function () {
            var string = this.resultString;
            var result = new Uint8Array(string.length);
            for (var i = 0; i < string.length; i++) {
                result[i] = string.charCodeAt(i);
            }
            return result.buffer;
        });
    };
}
ReadFile();
11
répondu Pavan Kumar Jorrigala 2015-09-07 23:48:46

je pense que vous touchez un bug de Firefox. Cependant, comme vous l'avez souligné, readAsArrayBuffer se comporte correctement dans tous les navigateurs pris en charge à L'exception de Firefox alors que readAsBinaryString est supporté par tous les navigateurs sauf IE.

par conséquent, il est possible de préférer readAsBinaryString lorsqu'il existe et de rebasculer vers readAsArrayBuffer autrement.

function readFileAsArrayBuffer(file, success, error) {
    var fr = new FileReader();
    fr.addEventListener('error', error, false);
    if (fr.readAsBinaryString) {
        fr.addEventListener('load', function () {
            var string = this.resultString != null ? this.resultString : this.result;
            var result = new Uint8Array(string.length);
            for (var i = 0; i < string.length; i++) {
                result[i] = string.charCodeAt(i);
            }
            success(result.buffer);
        }, false);
        return fr.readAsBinaryString(file);
    } else {
        fr.addEventListener('load', function () {
            success(this.result);
        }, false);
        return fr.readAsArrayBuffer(file);
    }
}

Utilisation:

readFileAsArrayBuffer(input.files[0], function(data) {
    var array = new Int8Array(data);
    output.value = JSON.stringify(array, null, '  ');
    window.setTimeout(ReadFile, 1000);
}, function (e) {
    console.error(e);
});

violon de travail:https://jsfiddle.net/Lv5y9m2u/6/

Navigateur Support:

  • Firefox: Uses readAsBinaryString, qui n'est pas problématique.
  • IE >= 10: Uses readAsArrayBuffer qui est supporté.
  • IE < = 9: la totalité FileReader L'API n'est pas supportée.
  • Presque tous les autres navigateurs:readAsBinaryString.
4
répondu FelisCatus 2015-09-07 09:22:04