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:
- rechercher un fichier texte qui comporte 10 caractères (10 n'est pas un nombre magique - je suis juste en utilisant un exemple)
- Observer que le résultat est un tableau de 10 éléments représentant les codes de caractères de chaque élément
- pendant que ceci est encore en cours d'exécution, supprimez 5 caractères du fichier et sauvez
- 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)
- maintenant Ajouté 10 caractères (donc le fichier est maintenant 15 caractères de long)
- 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/
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();
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
.