【问题标题】:Store more than 5mb on client with Javascript使用 Javascript 在客户端存储超过 5mb
【发布时间】:2013-09-30 19:16:30
【问题描述】:

我想在客户端浏览器中存储超过 5mb 的空间。浏览器可以是 Firefox、Chrome、Internet Explorer、Safari (iOS) 或 Windows Phone 8 浏览器。我首先想到的是 localStorage,因为它已经在上述浏览器中实现了。

作为一项额外功能,它应该可以在特殊浏览器上节省超过 5mb 的空间。因此,我首先检查浏览器引擎,然后选择最佳保存方法。我只需要存储键值对。

如果我尝试下面的代码,我在 chrome 上从未或非常晚地编写过它。 iPhone 工作(webSQL)除了 iOS 7。在 iOS 7 中是一个已知的浏览器错误,它会导致数据库崩溃。我希望他们能尽快修复它:-)

这可以实现吗?以下是我的第一个想法:

<!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>

【问题讨论】:

  • 如果您需要同时使用 IndexedDB 和 Web SQL api,我建议您查看 JayData (jaydata.org),它旨在“提供一个标准的、跨平台的库和方法来访问和操纵来自各种来源的数据。”
  • 这个问题似乎离题了,因为它不太可能帮助未来的读者。

标签: javascript html local-storage indexeddb web-sql


【解决方案1】:

我现在使用 localForage。它对我来说效果很好。它会自动选择在用户浏览器中保存数据的最佳方法。

请看这里:https://github.com/mozilla/localForage

【讨论】:

    【解决方案2】:

    看起来非常不错的实现 - 简洁且适用于大多数情况。

    您可以检查window.indexedDBwindow.openDatabase,而不是检查userAgent。

    在 indexeddb 实现中,索引主键不是必需的,因为它已经被索引了。对于整条记录的计数,不需要键范围。

    【讨论】:

    • 问题是最新版本的 iOS 中有一个 javascript 错误,不允许扩展数据库的大小 :-( 所以在他们解决这个问题之前我不能信任 window.indexedDB 或window.openDatabase...
    • 配额授予边缘错误与检测window.openDatabase无关
    猜你喜欢
    • 2011-12-25
    • 2011-09-10
    • 2020-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多