Using FileReader.readAsArrayBuffer() on changed files in Firefox
Interesting, looks like Firefox is caching the buffer size even the file is modified.
You can refer to this link, replaced readAsArrayBuffer
with is custom functionality which uses readAsBinaryString
. Its working fine in Firefox and 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();
I think you are hitting a bug of Firefox. However, as you pointed out, readAsArrayBuffer
behaves correctly in every supported browser except Firefox while readAsBinaryString
is supported by every browser except IE.
Therefore, it is possible to prefer readAsBinaryString
when it exists and fail back to readAsArrayBuffer
otherwise.
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);
}
}
Usage:
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);
});
Working fiddle: https://jsfiddle.net/Lv5y9m2u/6/
Browser Support:
- Firefox: Uses
readAsBinaryString
, which is not problematic. - IE >= 10: Uses
readAsArrayBuffer
which is supported. - IE <= 9: The entire
FileReader
API is not supported. - Almost all other browsers: Uses
readAsBinaryString
.