sffc
sffc

Reputation: 6424

Extracting partial data out of a FileReader's ArrayBuffer

I am using the HTML5 FileReader readAsArrayBuffer() method to read a file into memory. According to the spec (linked above):

While processing the read, as data from the blob becomes available, user agents should queue tasks to update the result with partial Blob data as an ArrayBuffer [TypedArrays] object containing the bytes read until the read is complete, to accompany the firing of progress events. On getting, the result attribute returns partial Blob data representing the number of bytes currently loaded (as a fraction of the total) [ProgressEvents], as an ArrayBuffer [TypedArrays] object; user agents must return at least one such ArrayBuffer [TypedArrays] while processing this read method. The last returned value is at completion of the read.

However, in the browsers I have tested (Firefox, Chrome, and Opera), the reader.result property does not seem to be consistently updated. For example:

var reader = new FileReader(), pos = 0;

reader.addEventListener("progress", function(event){
    console.log(reader.result);
    var content = new Uint8Array(reader.result, pos, event.loaded);
    pos = event.loaded;

    // do stuff with the content down here
});

document.getElementById("fileInput").addEventListener("change", function(event){
    reader.readAsArrayBuffer(event.target.files[0]);
});

where there is an HTMLInputElement of ID fileInput and type file. When a sufficiently large file is chosen and the callback runs, here is what happens on the console (this example is from Chrome):

null
Uncaught TypeError: Type error

I believe that the TypeError arises because the array view Uint8Array cannot read the chunk from the ArrayBuffer because the ArrayBuffer is null.

Strangely, if the file is large but not too large, a few progress events will actually run successfully.

How do you reliably implement a FileReader's ArrayBuffer to provide you the data you need upon a "progress" event?

Upvotes: 2

Views: 2492

Answers (1)

Rohit Singh Sengar
Rohit Singh Sengar

Reputation: 999

I guess you can read the ArrayBuffer once file is loaded. Following function takes care of large files too. Hope it helps,

function onfilechange(evt) {
var reader = new FileReader(); 
reader.onload = function(evt) {
  var chars  = new Uint8Array(evt.target.result);
  var CHUNK_SIZE = 0x8000; 
  var index = 0;
  var length = chars.length;
  var result = '';
  var slice;
  while (index < length) {
    slice = chars.subarray(index, Math.min(index + CHUNK_SIZE, length)); 
    result += String.fromCharCode.apply(null, slice);
    index += CHUNK_SIZE;
  }
  // Here you have file content as Binary String in result var
};
reader.readAsArrayBuffer(evt.target.files[0]);
}

Upvotes: 2

Related Questions