前言:昨天领导让我做个工作,具体内容是什么呢,意思就是在没有起任何本地服务的情况下,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不可行。