JavaScript读取本地db文件

7,227 阅读2分钟

前言:昨天领导让我做个工作,具体内容是什么呢,意思就是在没有起任何本地服务的情况下,JavaScript能否读取本地db文件,让我调研一下。一开始没听懂,有点懵逼。好嘛,可以尝试一下。于是开始查资料,以下内容为过程,记录一下。

网上说的最多的有两种方案。一种是使用浏览器自带的db数据库 第二种是使用sql.js。好的,一个一个看

一:浏览器自带db数据库

谷歌浏览器配置了这种轻量的文件型数据库,但要注意的是chrom有自己的数据库路径,要在C:\Users\A\AppData\Local\Google\Chrome\User Data\Default\databases下去建立数据库。因为这种方法不符合我现有的项目,所以不多叙述。

二:sql.js

github地址:github.com/kripken/sql…

首页上写了很多种方法和demo,用户可以根据需求选择自己合适的方法。我首先尝试了ajax,代码如下

initSqlJs({ locateFile: filename => `./dist/${filename}` }).then(function (SQL) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', './data.db', true);
    xhr.responseType = 'arraybuffer';
    xhr.onload = e => {
        var uInt8Array = new Uint8Array(this.response);
        var db = new SQL.Database(uInt8Array);
        var contents = db.exec("SELECT * FROM FriendInfo where FRIEND_NICKNAME = '熊巧'");
        contents.getAsObject({}); // {col1:1, col2:111}
        contents.bind({});
        while (contents.step()) { //
            var row = contents.getAsObject();
            console.log('Here is a row: ' + JSON.stringify(row));
        }
    };
    xhr.send();
})

浏览器输出结果

结果以为这样就结束了,简直tooyoung too simple

这必须是在有服务的情况下,而我现在需要的是没有本地服务也能够读取db文件的方案。好,继续找。通篇下来,只有一个方案可行,就是通过上传文件的方式,在input type="file" 的change回调中进行读取,实践结果:可行。代码如下

html

<input type='file' id='dbfile'>

js

initSqlJs({ locateFile: filename => `./dist/${filename}` }).then(function (SQL) {
    var dbFileElm = document.getElementById('dbfile');
    dbFileElm.onchange = () => {
        var f = dbFileElm.files[0];
        var r = new FileReader();
        r.onload = function () {
            var Uints = new Uint8Array(r.result);
            db = new SQL.Database(Uints);
            var stmt = db.prepare("SELECT * FROM FriendInfo where FRIEND_NICKNAME = '熊巧'");
            stmt.getAsObject({}); // {col1:1, col2:111}
            stmt.bind({});
            while (stmt.step()) { //
                var row = stmt.getAsObject();
                console.log('Here is a row: ' + JSON.stringify(row));
            }
        }
        r.readAsArrayBuffer(f);
    }
})

浏览器输出结果与上同

but这种让用户手动将所有db文件全部上传一遍的方法简直太智障且反人类。

但是如果跟我情况不同,是在有服务的情况下,sql.js完全可行。需要注意的是虽然sqlite功能强大,轻量,读取速度快。但是那是在直接操作数据库的情况下,如果让前端直接读取本地的sqlite.db文件,速度相当慢,有兴趣的朋友可自行尝试。

后言:我后来还是想将上传文件的方案运用到自己的项目,看是否可行。但是frameset之间相互通信,在域名相同的情况下可以使用postmessage。但是前提是在域名相同的情况下。但是本地打开html文件,哪里的域名,so不可行。