readasdataurl - read file javascript
Uso de FileReader.readAsArrayBuffer() en archivos modificados en Firefox (2)
Creo que estás golpeando un error de Firefox. Sin embargo, como señaló, readAsArrayBuffer
comporta correctamente en todos los navegadores compatibles, excepto en Firefox, mientras que readAsBinaryString
es compatible con todos los navegadores, excepto IE.
Por lo tanto, es posible preferir readAsBinaryString
cuando exista y, en readAsArrayBuffer
contrario, volver a readAsArrayBuffer
.
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);
}
}
Uso:
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);
});
Fiddle de trabajo: https://jsfiddle.net/Lv5y9m2u/6/
Soporte del navegador:
- Firefox: utiliza
readAsBinaryString
, que no es problemático. - IE> = 10: utiliza
readAsArrayBuffer
que es compatible. - IE <= 9: no se admite la API completa de
FileReader
. - Casi todos los demás navegadores: utiliza
readAsBinaryString
.
Estoy encontrando un problema extraño con FileReader.readAsArrayBuffer
que solo parece afectar a Firefox (lo probé en la versión actual - v40). No puedo decir si estoy haciendo algo mal o si se trata de un error de Firefox.
Tengo algo de JavaScript que usa readAsArrayBuffer
para leer un archivo especificado en un campo <input>
. En circunstancias normales, todo funciona correctamente. Sin embargo, si el usuario modifica el archivo después de seleccionarlo en el campo <input>
, readAsArrayBuffer
puede confundirse.
El ArrayBuffer
que recibo de readAsArrayBuffer
siempre tiene la longitud original del archivo. Si el usuario cambia el archivo para hacerlo más grande, no obtengo ninguno de los bytes después del tamaño original. Si el usuario cambia el archivo para hacerlo más pequeño, el búfer sigue siendo del mismo tamaño y el "exceso" en el búfer está lleno de códigos de caracteres 90 (mayúscula "Z" si se ve como una cadena).
Dado que este código es muy simple y funciona perfectamente en todos los demás navegadores que probé, creo que es un problema de Firefox. Lo he reportado como un error a Firefox, pero quiero asegurarme de que esto no es algo obvio que estoy haciendo mal.
El comportamiento puede ser reproducido por el siguiente fragmento de código. Todo lo que tienes que hacer es:
- Busque un archivo de texto que tenga 10 caracteres (10 no es un número mágico, solo lo estoy usando como ejemplo)
- Observe que el resultado es una matriz de 10 elementos que representan los códigos de caracteres de cada elemento.
- Mientras esto se está ejecutando, elimine 5 caracteres del archivo y guarde
- Observe que el resultado sigue siendo un conjunto de 10 elementos: los primeros 5 son correctos pero los últimos 5 son todos 90 (mayúscula Z)
- Ahora se agregan 10 caracteres (por lo tanto, el archivo ahora tiene 15 caracteres de longitud)
- Observe que el resultado sigue siendo una matriz de 10 elementos; los últimos 5 no se devuelven
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>
En caso de que el fragmento no funcione, el código de ejemplo también está disponible como JSFiddle aquí: https://jsfiddle.net/Lv5y9m2u/
Interesante, parece que Firefox está almacenando en caché el tamaño del búfer, incluso el archivo está modificado.
Puede consultar este link , reemplazado por readAsArrayBuffer
con una funcionalidad personalizada que utiliza readAsBinaryString
. Está funcionando bien en Firefox y 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();