简体   繁体   中英

Store more than 5mb on client with Javascript

i want to store more than 5mb in the client browser. The Browser can be Firefox, Chrome, Internet Explorer, Safari (iOS) or Windows Phone 8 Browser. My first thought was about localStorage as it is already implemented in the mentioned browsers.

As a bonus feature it should be possible to save more than 5mb on special browsers. Therefore i first check the browser engine and then select the best saving method. I only need to store key - value pairs.

if i try the code below i wrote it never or extremly late on chrome. iPhone works (webSQL) except iOS 7. In iOS 7 is a known browser bug which crashes the DB. I hope they will fix it soon :-)

Is this possible to implement? Below is my first idea:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <title>Datenbank Test</title>

    <script type="text/javascript">

        alert(navigator.userAgent.toLowerCase());

        var db = {};
        db.debug = true;
        db.__browser = navigator.userAgent.toLowerCase();
        db.__database = 'fDB';
        db.__driver = undefined;

        db.initialize = function () {
            if (db.__browser.search(/(chrome|firefox|msie)/) > -1) {
                db.__driver = 'indexedDB';
                db.indexedDB.initialize();
            }
            else if (db.__browser.search(/(iphone|safari)/) > -1) {
                db.__driver = 'webSQL';
                db.webSQL.initialize();
            }
            else {
                db.__driver = 'localStorage';
            }

        };

        db.setItem = function (iKey, iVal) {
            switch (db.__driver) {
                case 'indexedDB':
                    db.indexedDB.setItem(iKey, iVal);
                    break;
                case 'webSQL':
                    db.webSQL.setItem(iKey, iVal);
                    break;
                case 'localStorage':
                    localStorage.setItem(iKey, iVal);
                    break;
                default:
                    if (db.debug) {
                        console.log('An error occured.');
                    }
            }
        }

        db.getItem = function (iKey, callback) {
            switch (db.__driver) {
                case 'indexedDB':
                    db.indexedDB.getItem(iKey, function (data) {
                        callback(data);
                    });
                    break;
                case 'webSQL':
                    db.webSQL.getItem(iKey, function (data) {
                        callback(data);
                    });
                    break;
                case 'localStorage':
                    callback(localStorage.getItem(iKey));
                    break;
                default:
                    if (db.debug) {
                        console.log('An error occured.');
                    }
            }
        };

        db.setItemsBulk = function (items) {
            switch (db.__driver) {
                case 'indexedDB':
                    db.indexedDB.setItemsBulk(items);
                    break;
                case 'webSQL':
                    db.webSQL.setItemsBulk(items);
                    break;
                case 'localStorage':
                    alert('Not implemented yet. sorry :-(');
                    break;
                default:
                    if (db.debug) {
                        console.log('An error occured.');
                    }
            }
        };

        db.count = function (callback) {
            switch (db.__driver) {
                case 'indexedDB':
                    db.indexedDB.count(function (data) {
                        callback(data)
                    });
                    break;
                case 'webSQL':
                    // TODO
                    break;
                case 'localStorage':
                    callback(localStorage.length);
                    break;
                default:
                    if (db.debug) {
                        console.log('An error occured.');
                    }
            }
        };

        db.indexedDB = {};
        db.indexedDB.__dbHandler = undefined;
        db.indexedDB.__request = undefined;

        db.indexedDB.initialize = function () {
            window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
            window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
            window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;

            db.indexedDB.__request = window.indexedDB.open(db.__database, 1337);
            db.indexedDB.__request.onsuccess = function (e) {
                console.log('IndexedDB opened');
                db.indexedDB.__dbHandler = e.target.result;
            };
            db.indexedDB.__request.onupgradeneeded = function (e) {
                console.log('IndexedDB upgradeNeeded');
                db.indexedDB.__dbHandler = e.target.result;
                if (db.indexedDB.__dbHandler.objectStoreNames.contains('data')) {
                    db.indexedDB.__dbHandler.deleteObjectStore('data');
                }
                var objectStore = db.indexedDB.__dbHandler.createObjectStore('data', { keyPath: "iKey" });
                objectStore.createIndex('iKey', 'iKey', { unique: true });
            };
        };

        db.indexedDB.setItem = function (iKey, iVal) {
            var trans = db.indexedDB.__dbHandler.transaction(['data'], "readwrite");
            var store = trans.objectStore("data");
            var request = store.put({ iKey: iKey, iVal: iVal });
        };

        // Use the callback to get the values
        db.indexedDB.getItem = function (iKey, callback) {
            try {
                var trans = db.indexedDB.__dbHandler.transaction(['data'], "readwrite");
                var store = trans.objectStore("data");
                var request = store.get(iKey);
                request.onsuccess = function (e) {
                    callback(request.result != null && request.result.iVal != null ? request.result.iVal : null);
                };
                request.onerror = function (e) {
                    if (db.debug)
                        console.log(e);
                };
            } catch (e) {
                alert(e);
            }

        };

        db.indexedDB.setItemsBulk = function (items) {
            if (!items.length) {
                return;
            }
            var trans = db.indexedDB.__dbHandler.transaction(["data"], "readwrite");
            var store = trans.objectStore("data");
            var request = store.put(items[0]);
            request.onsuccess = function onSuccessHandler() {
                items = items.splice(1);
                if (!items.length) {
                    return;
                }
                request = store.put(items[0]);
                request.onsuccess = onSuccessHandler;
            };
        };

        db.indexedDB.count = function (callback) {
            var trans = db.indexedDB.__dbHandler.transaction(["data"], "readwrite");
            var store = trans.objectStore("data");
            var keyRange = IDBKeyRange.lowerBound(0);
            var cursorRequest = store.openCursor(keyRange);
            var count = 0;
            cursorRequest.onsuccess = function (e) {
                var result = e.target.result;
                result ? ++count && result.continue() : callback(count);
            };

        };

        db.webSQL = {};
        db.webSQL.__dbHandler = undefined;

        db.webSQL.initialize = function () {
            db.webSQL.__dbHandler = openDatabase('fDB', '1.0', 'place for comment', 50 * 1024 * 1024);
            db.webSQL.__dbHandler.transaction(function (tx) {
                tx.executeSql('CREATE TABLE IF NOT EXISTS data (iKey unique, iVal VARCHAR(255))');
            });
        }

        db.webSQL.setItem = function (iKey, iVal) {
            db.webSQL.__dbHandler.transaction(function (tx) {
                tx.executeSql('INSERT OR REPLACE INTO data (iKey, iVal) VALUES (?, ?)', [iKey, iVal]);
            });
        };

        db.webSQL.getItem = function (iKey, callback) {
            try {
                db.webSQL.__dbHandler.transaction(function (tx) {
                    tx.executeSql('SELECT iVal FROM data WHERE iKey = ?', [iKey], function (tx, results) {
                        //console.log(results.rows.item(0).iVal);
                        callback(results.rows.item(0).iVal);
                    });
                });
            }
            catch (e) {
                alert('ERROR: ' + e);
            }
        };

        db.webSQL.setItemsBulk = function (items) {
            db.webSQL.__dbHandler.transaction(function (tx) {
                for (var i = 0; i < items.length; i++) {
                    tx.executeSql('INSERT OR REPLACE INTO [data] (iKey, iVal) VALUES (?, ?)', [items[i].iKey , items[i].iVal]);
                }
            });
        }

        db.webSQL.count = function (callback) {
            db.webSQL.__dbHandler.transaction(function (tx) {
                tx.executeSql('SELECT COUNT(*) AS c FROM data', [], function (tx, data) {
                    callback(data.rows.item(0).c);
                });
            });
        };

        function bigData() {
            var items = [];
            for (var i = 1; i < 40000; i++) {
                items.push({ iKey: i, iVal: "Now this is the story all about how My life got flipped turned upside down. And Id like to take a minute just sit right there Ill tell you how I became the prince of a town called Bel Air" });
            }
            console.log(items);
            db.setItemsBulk(items);
        }

        db.initialize();
    </script>



</head>
<body>
    Dies ist ein Datenbank-Test
    <button onclick="db.setItem('browser', navigator.userAgent);">AddItem</button>
    <button onclick="db.getItem('browser', function(e) {alert(e);});">GetItem</button>
    <button onclick="db.count(function (e) { alert(e); });">Gebe Count aus.</button>

    <button onclick="bigData();">Insert BIG DATA</button>
    <button onclick="db.getItem(50, function (d) { document.getElementById('entry').innerHTML = 'Eintrag 50: ' + d; });">Load Sample Entry</button>

    <button onclick="db.__driver = 'localStorage';">driver = localStorage</button>
    <button onclick="db.__driver = 'webSQL';">driver = WebSQL</button>
    <button onclick="db.__driver = 'indexedDB';">driver = indexedDB</button>

    <div id="driver"></div>
    <div id="entry"></div>

    <script type="text/javascript">
        document.getElementById('driver').innerHTML = 'Datenbank: ' + db.__driver;

    </script>
</body>
</html>

i now use localForage. It works very well for me. it automatically selects the best method for saving data in the user's browser.

See here: https://github.com/mozilla/localForage

Look like very nice implementation - concise and usable for most cases.

Instead of checking userAgent, you may check window.indexedDB or window.openDatabase .

In indexeddb implementation, indexing primary key is not necessary since it already indexed. For counting whole records, key range is not necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM