Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ZIP (compress) an SQLITE database file in Cordova?

I need a "support" mode for my Cordova app currently running on Windows Mobile and iOS. For this purpose, I need to compress an sqlite database file and upload it to a server. The database has to be compressed as it might grow over 250MB and the upload has to work without a wifi connection.

Searching the web brought up different approaches but all of them were outdated or did only solve my problem for either iOS or Windows Mobile. For example, when using the Cordova file plug-in I've encountered this in the plug-in documentation:

Supported Platforms

Android iOS OS X Windows* Browser

  • These platforms do not support FileReader.readAsArrayBuffer nor FileWriter.write(blob).

This was my approach: Cordova - Zip files and folders on iOS

Any ideas?

like image 752
MichaelS Avatar asked Oct 16 '22 11:10

MichaelS


1 Answers

I would suggest you to give FileReader() a second chance.

In my case wich may be very similar to yours, I read a file using FilerReader.readAsArrayBuffer and after that, compress it using the JSZip library: http://stuartk.com/jszip

In opposition to the cordova-file-plugin's API documentation (https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/) "Windows*"->"These platforms do not support FileReader.readAsArrayBuffer nor FileWriter.write(blob))" I experienced that readAsArrayBuffer works under Windows UWP platform, but slower.

So in my case, with a file of approx. 50M I had to wait for nearly 2min for the whole process to finish!

Try following this example:

You'll need to adapt to your paths but this runs for WINDOWS UWP and IOS (didn't test it with Android but that was not your question).

Also, you'll need to implement your own error handler (errorHandler). This solution uses Promises since you'll have to wait for the file beeing read and compressed.

PS1: Always be sure your "device ready's event" as been fired in order to access plugins.

PS2: You may encouter no access permission on the database file, this may be related to the fact, that it's being used by another process. Be sure the database is closed. SQLITE:

        var sqlite = window.sqlitePlugin.openDatabase({ name: 'yourdb.db', location: 'default' });
        sqlite.close(function () {
            console.log("DONE closing db");
        }, function (error) {
            console.log("ERROR closing db");
            console.log(JSON.stringify(error));
        });

"ZIP" function:

    function zipFile(sourceFileName, targetFileName) {
    return new Promise(function (resolve, reject) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
            fs.root.getFile(sourceFileName, { create: false, exclusive: false }, function (fe) {
                fe.file(function (file) {
                    var reader = new FileReader();
                    reader.onloadend = function (data) {
                        var zip = new JSZip();
                        zip.file(sourceFileName, data.target.result);
                        zip.generateAsync({
                            type: "blob",
                            compression: "DEFLATE",
                            compressionOptions: {
                                level: 9
                            }
                            // level 9 means max. compression
                            // this may also take some time depending on the size of your file
                            // I tested it with a 50M file, it took about 65 sec.
                        }).then(

                            // following is post-zip in order to transfer the file to a server
                            function (blob) {
                                fs.root.getFile(targetFileName, { create: true, exclusive: false }, function (newzip) {
                                    writeFile(newzip, blob, "application/zip").then(function () {
                                        var f = blob;
                                        var zipReader = new FileReader();

                                        zipReader.onloadend = function (theFile) {
                                            var base64 = window.btoa(theFile.target.result);
                                            resolve(base64);
                                        };
                                        // need to "resolve" the zipped file as base64 in order to incluse it in my REST post (server-upload)
                                        zipReader.readAsBinaryString(f);
                                    });

                                });

                            }
                        )
                    };
                    reader.readAsArrayBuffer(file); 
                    // this may take some time depending on the size of your file
                    // I tested it with a 50M file, it took about 72 sec.
                }, errorHandler);
            }, errorHandler);
        });
    });
}

ex call:

if (window.cordova) {
    document.addEventListener('deviceready', function () {
        zipFile("yourDatabaseFileName.db","compressedDatabaseFile.zip");
    });
} 
like image 81
drallebas Avatar answered Nov 15 '22 07:11

drallebas