javascriptcordovablobfileapi

How to merge two array buffers into one?


I have a big blob for a rar file. To uncompress it I had to use this library unrar.js

The blob I am testing with is about 23MB, to readAsArrayBuffer then feed it to unrar.js I had to slice it.

For some reason unrar.js does not play well with sliced blobs--it would throw an unknown archive type error if the sliced blob range does not start with 0 or end with blob.size . -weird?-

The only workaround I can think of is to read the blob as slices then collect it back again in the onloadend function. -is that even possible?-

Collect the array buffers in one array then feed it to unrar.js to uncompress the file as if it was read from one blob.

If this sound too annoying for you I would appreciate any other way to read rar files in javascript/phonegap environment.


Solution

  • I am not sure I fully understand why the blob is segmented, but if they are, you could probably do something like:

    var blobs = [new Blob(['Hello ']),new Blob(['World'])];
    var buffers = [];
    var buffersFilled = 0;
    
    for(var i=0; i < blobs.length; i++) {
      buffers.push(new Uint8Array()); 
    }
    
    
    for(var i=0; i<blobs.length; i++) {
        var fileReader = new FileReader();
      
        fileReader.onload = (function(i,fileReader) {
          return function(){
            buffers[i] = fileReader.result;
            isBuffersDone();
          }
        })(i,fileReader);
        fileReader.readAsArrayBuffer(blobs[i]);
    }
    
    function isBuffersDone() {
      buffersFilled++;
      if(buffersFilled >= blobs.length) {
        var result = spliceBuffers();  
        
        //*****************
        // result is the spliced together buffers that could be given to unrar.js
        console.log(result);
      }
    }
    
    function spliceBuffers() {
      var tmpResult = new Uint8Array();
      
      for(var i=0; i < buffers.length; i++) {
        tmpResult = appendBuffer(tmpResult, buffers[i]);
      }
      
      return tmpResult;
    }
    
    
    
    
    function appendBuffer(buffer1, buffer2) {
      var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
      tmp.set(new Uint8Array(buffer1), 0);
      tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
      return tmp;
    };

    While the above works, take it with a grain of salt because with my limited understanding of what you are doing I don't know this is the best solution