能否以无服务端方式使用sql.js实现浏览器端SQLite只读访问?
需求可行性结论
完全可以实现,无需搭建服务器,仅靠本地文件即可完成浏览器端对SQLite数据库的只读访问,核心要解决浏览器对file协议的默认安全限制,以及sql.js的正确配置。
具体操作方案
分两种可选方案,按需选择即可:
方案一:无需修改浏览器配置(更安全,推荐)
无需改动浏览器设置,通过让用户手动选择本地数据库文件的方式绕过安全限制,操作步骤如下:
- 本地文件夹准备好以下3类文件:
- sql.js依赖文件:
sql-wasm.js、sql-wasm.wasm(和html文件放在同一目录下) - 你的SQLite数据库文件,比如
data.db - 新建本地html文件,比如
sqlite-viewer.html
- sql.js依赖文件:
- 把以下代码写入
sqlite-viewer.html,代码已经内置只读限制,仅允许执行SELECT查询:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>本地SQLite只读查询工具</title> <script src="sql-wasm.js"></script> </head> <body> <input type="file" id="dbFileInput" accept=".db,.sqlite,.sqlite3"> <div id="result"></div> <script> let db = null; // 初始化sql.js initSqlJs({ locateFile: filename => `./${filename}` }).then(SQL => { // 监听文件选择 document.getElementById('dbFileInput').addEventListener('change', e => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const uInt8Array = new Uint8Array(e.target.result); // 加载数据库 db = new SQL.Database(uInt8Array); alert('数据库加载成功,仅支持只读查询'); // 这里可以替换成你需要执行的固定查询语句,或者加输入框让用户输入 runReadOnlyQuery('SELECT * FROM your_table_name LIMIT 10'); }; reader.readAsArrayBuffer(file); }); }); // 只读查询方法,自动过滤非SELECT操作 function runReadOnlyQuery(sql) { if (!db) { alert('请先选择数据库文件'); return; } // 过滤非查询操作,实现只读限制 const trimSql = sql.trim().toLowerCase(); if (!trimSql.startsWith('select')) { alert('仅允许执行SELECT查询操作'); return; } try { const res = db.exec(sql); // 格式化结果输出 document.getElementById('result').innerText = JSON.stringify(res, null, 2); } catch (e) { alert('查询执行错误:' + e.message); } } </script> </body> </html>
- 直接双击打开
sqlite-viewer.html,点击文件选择框选中你本地的.db数据库文件即可执行只读查询。
方案二:无需手动选择数据库文件(需修改浏览器启动参数)
如果需要页面加载时自动读取同文件夹下的数据库文件,不需要用户手动选择,可按以下步骤操作:
- 关闭所有Chrome/Edge浏览器窗口,右键浏览器桌面快捷方式,选择「属性」
- 在「目标」输入框的原有路径末尾,添加空格和参数
--allow-file-access-from-files,点击保存 - 用修改后的快捷方式打开浏览器,把以下代码写入你的html文件即可自动加载同目录下的
data.db文件:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>自动加载本地SQLite</title> <script src="sql-wasm.js"></script> </head> <body> <div id="result"></div> <script> initSqlJs({ locateFile: filename => `./${filename}` }).then(async SQL => { // 直接读取同目录的数据库文件 const res = await fetch('./data.db'); const buf = await res.arrayBuffer(); const db = new SQL.Database(new Uint8Array(buf)); // 执行只读查询,过滤规则和方案一一致即可 const queryRes = db.exec('SELECT * FROM your_table_name LIMIT 10'); document.getElementById('result').innerText = JSON.stringify(queryRes, null, 2); }); </script> </body> </html>
常见失败原因排查
你之前尝试代码无效大概率是以下问题导致:
sql-wasm.wasm文件缺失或者路径配置错误,导致sql.js初始化失败- 没有配置浏览器参数的前提下,直接用fetch加载本地db文件触发跨域限制,加载失败
- 没有做SQL操作过滤,不符合只读的需求
内容的提问来源于stack exchange,提问作者Bill Bell
相关产品推荐
相关产品推荐

