如何在Cordova中读/写本地json或文本



我正在尝试用Cordova读取www中的JSON文件。

我正在尝试很多系统、测试和解决方案,但它们一个接一个地失败了。

最简单的概念(fetch(

结果:本地工作。在应用程序上:如果使用cordova.file.dataDirectory,则"获取失败"。结果是:"尝试获取资源时出现NetworkError"。

document.addEventListener('click', test ,true);
document.addEventListener('touchstart', test ,true);
function test(){
alert("try fetch");
const jsonFile = "./geoita.json"; // fail on app
const jsonFile = cordova.file.dataDirectory+"geoita.json"; //security
var headers = new Headers({
"Content-Type": "text/plain",
"Accept": "text/plain"
});
window.fetch( jsonFile, headers )
.then( resp => resp.json() )
.then( json => {
console.log(json);
alert("Result: "+json);
document.body.innerHTML=JSON.stringify(json);

})
.catch(function(error) {
console.log('ERROR: ' + error.message);
alert('ERROR: ' + error.message);
});
};

测试2(请求(

结果:文件安全。您无法获取文件,因此无法读取。

var req = new XMLHttpRequest();
req.onreadystatechange = () =>
{
console.log("try in api style...");
if (req.readyState==4 && req.status==200)
{
console.log("reading...");
let json = JSON.parse(req.responseText);  
console.log(json);
}
else {
console.log("try in api style - error: "+req.readyState);
}
}
req.open("GET",(cordova.file.dataDirectory+"geoita.json"),true);
req.send();

测试3(遵循官方指南(

结果:找不到文件或编码错误。

const filePath = cordova.file.applicationDirectory+"geoita.json"; //return error code 5 ENCODING_ERR
//const filePath = "www/geoita.json"; // return error  1 NOT_FOUND_ERR
//const filePath ="geoita.json"; 
//const filePath = cordova.file.applicationDirectory+"geoita.txt"; // not changed
window.resolveLocalFileSystemURL( filePath ,
fileEntry => {
console.log("file object ready");
fileEntry.file(
File => {
console.log("content: ",File);
var reader = new FileReader();
reader.onloadend = function(evt)
{
console.log("read success",evt.target.result);
};
reader.readAsText(File);
});
}, error => console.error(error) );

我继续做很多测试,但我不明白出了什么问题。我不明白为什么读取Cordova的www文件夹中的本地文件如此困难。

我该怎么做?

更新

经过32次测试后,解决方案是错误的。

不幸的是,我刚刚意识到他不是从www文件夹写文件的。你可以做的是"从变量中创建一个文件,在永久文件中历史化它,然后重读它。它仍然没有像我当时想要的那样读取。

测试过程中发生的事情只是之前测试的结果,我"手动将文件复制到变量中",因此我在不知不觉中保存了它,随后被恢复,就好像它在读取本地文件一样(当然,这是相同的(

不幸的是,我仍然找不到读取该文件的解决方案。如果你意识到了,就写吧!

对于这个例子,我们有两种类型的数据。

1( 是json消息中的一个简单var;

2( 这是www目录中的一个本地文件(然后手动创建一个文件,您可以恢复…一个带有虚假json数据的文本,类似于1中的文本(

步骤00

在项目中添加cordova文件插件

https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/index.html

步骤01

在config.xml 中

<platform name="android">
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="assets,root, files, cache, sdcard, cache-external, files-external" />
</platform>
<platform name="ios">
<preference name="iosPersistentFileLocation" value="Compatibility" />
<preference name="iosExtraFilesystems" value="assets,root, files,cache, sdcard, cache-external, files-external" />
</platform>

您可能还需要输入:

<access origin="*" /> <access origin="cdvfile://*"/> <access origin="file:///*"/>

步骤02

现在,在应用程序准备就绪后,例如:

if('cordova' in window)
{
document.addEventListener('deviceready', mytest);
// console.log('device');
}
else
{
document.addEventListener('DOMContentLoaded', mytest);
// console.log('web device');
}

在另一个联合it on事件中:

document.addEventListener('click', mytest,true);
document.addEventListener('touchstart', mytest,true);

步骤03

进入应用的功能

function mytest(){

// start for read (get the file and pass it on readFile method)
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
(fs)=> {
var fileName = "test.txt",
fileDir =  cordova.file.applicationDirectory.replace( cordova.file.applicationDirectory, ''), //cordova.file.applicationDirectory only get error on entry file
filePath = fileDir + fileName;
fs.root.getFile(
filePath,
null,
(fileEntry) => {
readFile(fileEntry)
}, fileEntryFail);
}, filesystemFail);

// start for write (set a file creator -> get data via var -> pass var on writeFile method)
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
(fs)=> {
var fileName = "test.txt",
fileDir =  cordova.file.applicationDirectory.replace( cordova.file.applicationDirectory, ''), //cordova.file.applicationDirectory only get error on entry file
filePath = fileDir + fileName;
fs.root.getFile(
filePath,
{ create: true, exclusive: false },
(fileEntry) => {
writeFile(fileEntry, filetowrite );
}, fileEntryFail);
}, filesystemFail);

// write a file whit data
function writeFile(fileEntry, dataObj) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwrite = function() {
alert("file write");
// readFile(fileEntry); // if you wont read after write it
};
fileWriter.onerror = function (e) {
alert("Failed file write: " + e.toString());
};
fileWriter.write(dataObj);
});
}

// read a file getted 
function readFile(fileEntry) {
alert('Reading file....');
fileEntry.file(function (fileEntry)
{
console.log("path to file: ",fileEntry.fullPath);
console.log("file to read: ",fileEntry.file);
var reader = new FileReader();
reader.onloadend = function()
{
alert("Successful file read");
// document.body.innerHTML = ""+this.result;
console.log("Successful file read: ",this.result);
// window.dataActive = JSON.parse(this.result);
// alert('dataActive was read as: ' + dataActive)
// displayFileData(fileEntry.fullPath + ": " + this.result);
};
reader.readAsText(fileEntry);
}, readFail );
};

// fails 
function filesystemFail (err) { alert("FS: DATA FAIL"); console.log(err.code);};
function fileEntryFail (err) { alert("File entry: FAIL"); };
function writeFail (err) { alert("Writing: DATA FAIL"); };
function readFail (err) { alert("Reading: DATA FAIL"); };

//data test via var
var filetowrite =  `{"message": "THIS IS SIMPLE TEST MESSAGE"}`
};  

下面是一些重要的结束语

保持对同一文件或数据进行测试的开始读取和开始写入显然是无用的。要么写文件然后读取,要么在本地直接读取。因此,对于您的测试,请一次评论两个中的一个。

将它们分开也是愚蠢的,因为只调用一次文件系统很容易优化系统。

然而,我把它们分开,给那些像我一样拘泥于逻辑的人一个清晰而实用的例子。

更新

解决方案:

在等待整个插件时,我正在测试构建:

A( 您必须"解锁"对config.xml中文件的访问,正如我上面解释的那样。

B( cordova文件插件只能写入、读取、删除应用程序内永久内存中的文件。(我会尽快发布比上面更好的型号(

C( fetch在任何情况下都不起作用。小心,它只适用于浏览器,但不适用于应用

D-1(我正在测试网上文件的写入和删除。我还需要时间。

D-2(可以通过XML请求以以下方式读取www中的文件:

var _filename = 'MYFILENAMEINWWW.txt',
_mimetype = 'text/plain'; // or application/json
function readfromwww(_mimetype,_filename,callback)
{

var request = new XMLHttpRequest();
request.overrideMimeType(_mimetype ); 
request.open("GET", _filename );
request.onreadystatechange = () =>
{
if(request.status > 300)
{
if(rs==404) console.log('file not found in www: ',request.status);
else console.log('error on request: ',request.status);
}
else if(request.responseText!=undefined && request.responseText!='')
{
//from json string to js obj content
if(_mimetype == "application/json")
callback(JSON.parse(request.responseText));
//return string into your file
else
callback(request.responseText);
}
}
request.send();
}
}
// now you can read a file in www calling the method:
readfromwww('text/plain', 'test.txt',
filecontent => {
console.log('OLE! INTO THE FILE: ',filecontent);
//not filecontent is the content of your file but... remember... the contents is loaded via ajax, isn't easy to storize it out this function.
});

您可以查看MongOGX,这是一个受MongoDB启发的前端数据库,您可以在其中保存JSON文档,它支持cordova

MongOGX是一个简单的基于JavaScript的文档存储/数据库通过MongoDB。它支持本地存储和应用程序数据存储(通过Cordova-Cordova插件文件(存储模式。它还支持加密(通过code.google.com/p/crypto-js-添加到此回购中(。

请参阅https://github.com/globules-io/MongOGX

我创建了一个函数,该函数用字符串返回promise,然后可以用JSON或任何您想要的东西对其进行解析。

此解决方案仅在Android平台上进行了检查

我也尝试过使用fetch和XMLHttpRequest来实现这一点,但没有成功的结果。

打字:

export function readFileFromWWW(filename: string) {
return new Promise<string>((resolve, reject) => {
getWWWFileEntry(filename, (fileEntry) => {
;(fileEntry as FileEntry).file(
(file) => {
const reader = new FileReader()
reader.onloadend = () => {
resolve(reader.result as string)
}
reader.readAsText(file)
},
() => {
reject(new Error('read went wrong'))
}
)
})
})
}
function getWWWFileEntry(
filename: string,
callback: (fileEntry: Entry) => void
) {
window.resolveLocalFileSystemURL(
`${window.cordova.file.applicationDirectory}www/${filename}`,
callback
)
}

最新更新