问题描述
我正在使用 react 构建一个 .html 页面,以便于访问我工作地点的复杂本地文件系统。这需要任何人都可以编辑。我决定使用 pouchdb 来处理一个数据库,该数据库存储了我所有的按钮以及附加到它们的链接。 这需要部署在多台计算机上。命令 npm run build 工作正常,但是,按钮数据库不在计算机之间共享,因为 pouchdb 数据库存储在 localstorage 中。
所以我想出了一种将邮袋数据库转储到 .json 文件的方法。 转储过程工作正常,但是当我尝试使用 pouchdb-load 插件从 .json 文件中获取数据时,出现 CORS 错误。
this.db.load('file:///./tracker.json').then(function () {
// done loading!
console.log(this.db)
}).catch(function (err) {
// HTTP error or something like that
console.log(err)
});
Access to XMLHttpRequest at 'file:///tracker.json' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http,data,chrome,chrome-extension,chrome-untrusted,https.
message: undefined
name: "unkNown"
status: 0
当我省略文件路径后面的“file:///”时,我得到以下信息:
yntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at index.js:16
at Array.forEach (<anonymous>)
at parseDump (index.js:12)
at loadString (index.js:32)
at index.js:87
at onSuccess (index-browser.js:288)
at index-browser.js:330
at XMLHttpRequest.xhr.onreadystatechange (index-browser.js:198)
该项目需要构建为本地 .html 文件,因为我们需要能够打开文件链接。 我该怎么做才能使 pouchdb-load 在这样的配置中工作? 我现在很迷茫,所以感谢任何帮助!我究竟做错了什么?是否有任何简单的技巧可以在没有用户任何操作的情况下从文件系统打开文件?有没有其他方法可以在文件系统上存储我的 pouchdb 数据库的副本?如果是这样,我怎么才能找回它?
解决方法
确实是可怕的 CORS 错误,真是太痛苦了!当然,CORS 是最必要的,没有它,本地文件漏洞就会泛滥。
显而易见的解决方案是通过 HTTP 提供文件,或者在本地 - 想到 nodejs - 或者从远程服务器提供。在这里,我提供了一种适合此用例的解决方法,但可能不适用于其他用例。
该解决方案取决于两个事实:浏览器允许加载相对于本地文档的本地脚本文件,pouchdb-load
支持从字符串加载数据库。
为了让那些从头开始的人受益,让我们从创建 CouchDB 数据库的转储开始。我使用 curl 和 jq1,2 制作适合导入的转储
curl -X GET "http://localhost:5984/sratch/_all_docs?include_docs=true"
| jq-win64 "{"""docs""": [.rows[].doc]}" > db.js
(以上来自 Windows 上的 VSCode 终端 - 因此是三重引号 ?)
好的,现在我们有了一个 .js 文件,对我来说看起来像这样
{
docs: [
{
_id: "a369bc7329751c1642476e752b000f8d",_rev: "1-6a0a8c1a35c6bb106fc3c53cdc99c034",id: "4567",user: "test2",address: {
city: "New York",},{
_id: "a369bc7329751c1642476e752b00290e",_rev: "1-29508c896c6c773775c2c46f67714aad",id: "4568",info: {
city: "Atlanta",// etc....
当然,这是一个扩展名为 .js 的 JSON 文件。为什么?让我们通过快速编辑转储文件将原始 JSON 更改为变量:
let CANNED_LOCAL_DB = {
docs: [
{
_id: "a369bc7329751c1642476e752b000f8d",// etc....
太好了,数据库现在是一个 JavaScript 对象。让我们加载它。
裸骨 HTML:
<html>
<body>
<script src="./db.js"></script>
<script src="./scripts/pouchdb.js"></script>
<script src="./scripts/pouchdb.memory.js"></script>
<script src="./scripts/pouchdb.load.js"></script>
<script src="./scripts/index.js"></script>
</body>
</html>
这是 index.js 代码,证明了这个概念。
// "local" db
const ldb = new PouchDB("ldb",{ adapter: "memory" });
// load the database from the object,stringified
ldb.load(JSON.stringify(CANNED_LOCAL_DB))
.then(() => {
CANNED_LOCAL_DB = undefined;
return ldb.info();
})
.then((info) => {
console.log(JSON.stringify(info,undefined,3));
})
.catch((err) => {
console.log(err.toString());
});
加载后固定的 db 对象设置为 undefined - 没有理由让它留在内存中。
请理解 db.js 是同步加载的,这可能会对大量罐装 db 产生丑陋的影响。这可能可以解决,但超出了本答案的范围。
1CouchDB dump to file and load from file
2jq,a lightweight and flexible command-line JSON processor