Search code examples
javascriptcordovasha1cordova-3cryptojs

Cordova calculate sha1 hash of large file without running out of memory


I am trying to use sha1 hashes as a means of checking for file changes, the problem is that when trying to calculate the hash of a larger file(50-100MB) the app throws a Fatal Exception because it ran out of memory.

Version information:

  • Cordova 3.5
  • Android 4.2.2
  • Galaxy Tab 2
  • org.apache.cordova.file 1.1.0
  • CryptoJS latest?
  • lib-typedarrays(module for CryptoJS) latest?
  • qjs latest

Here is what im using:

function _getFileChecksum(file){

    var deferred = Q.defer();
    if(typeof CryptoJS === 'undefined'){
        if(DEBUG){
            console.log('CryptoJS is required.');
        }
        return deferred.reject(new Error('CryptoJS is required.'));
    }

    var reader = new FileReader();

    reader.onload = function (evt) {
        if(DEBUG){
            console.log('_getFileChecksum: reader finished loading');
        }
        var arrayBuffer = evt.target.result;
        var wordArray = CryptoJS.lib.WordArray.create(arrayBuffer);
        var hash = CryptoJS.SHA1(wordArray);
        if(DEBUG){
            console.log('_getFileChecksum: hash = '+hash);
        }
        deferred.resolve(hash);
    };
    reader.onerror = function(anError){
        if(DEBUG){
            console.log('_getFileChecksum: reader error');
        }
        deferred.reject(anError);
    };
    reader.readAsArrayBuffer(file);

    return deferred.promise;
}

Now this works just fine for smaller files. But when i get to the larger ones thats where the problem happens. Does anyone know how i would calculate a sha1 has of a large file without running out of memory in the application?


Solution

  • I was able to get around the out of memory issue by adding

    android:largeHeap="true"
    

    in my AndroidManifest.xml in the <application /> tag

    <application android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name" android:largeHeap="true">