项目中有这么一个需求,要求不调后台接口,但是前端要有增删改的操作,这个时候可能会想到用uniapp
自带的原生API
uni.setStorageSync("key", "value")
进行存储,但是要考虑内存问题,原生自带的存储有限一般为5-10MB
,所以这个方案基本都排除了,后来经过查询资料发现用localfage
也可以,这个内存会一点50MB
,我就酷酷下载使用,但是报错了,再加上内存的原因,我就放弃这个方法了,再后来就用Android原生
的方法,获取系统文件
进行操作,哎,你还别说,真的可行,现在话不多说,直接上代码。
我是将数据的读取和写入封装到一个js文件了,使用的时候引入就可以。
首先需要检查manifest.json
中的配置是否正确开启"读写文件"相关设置。以下是关键点:
- 确保
manifest.json
中已勾选"读写文件"权限。
通过plus.io
可获取文件系统管理对象。
IO模块管理本地文件系统,用于对文件系统的目录浏览、文件的读取、文件的写入等操作
javascript
// 读取json文件
function getJsonData(path) { //path:路径
return new Promise(resolve => {
plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, fs => { //请求文件系统
fs.root.getFile(
path, {
create: true //当文件不存在时创建
}, fileEntry => {
fileEntry.file(function(file) {
let fileReader = new plus.io
.FileReader(); //new一个可以用来读取文件的对象fileReader
fileReader.readAsText(file, "utf-8"); //读文件的格式
fileReader.onerror = e => { //读文件失败
console.log("获取文件失败", fileReader.error);
// plus.nativeUI.toast("获取文件失败,请重启应用", {
// background: "#ffa38c",
// });
return;
};
fileReader.onload = e => { //读文件成功
let txtData = e.target.result ? e.target.result : JSON.stringify([]);
resolve(txtData);
// 回调函数内的值想返回到函数外部 就用promise+resolve来返回出去
};
});
}, error => {
// console.log("2新建获取文件失败", error);
// plus.nativeUI.toast("获取文件失败,请重启应用", {
// background: "#ffa38c",
// });
return;
});
},
e => {
// console.log("1请求文件系统失败", e.message);
// plus.nativeUI.toast("请求系统失败,请重启应用", {
// background: "#ffa38c",
// });
return;
}
);
});
};
// 写入josn文件
function changeData(path, writeData) { //参数1:上传路径,参数2:seek方法可设置文件操作指定位置,参数3:写入的json数据
plus.nativeUI.showWaiting("正在保存信息");
return new Promise(resolve => {
plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, fs => {
fs.root.getFile(path, {
create: true
}, fileEntry => {
fileEntry.file(file => {
fileEntry.createWriter(writer => {
//plus.nativeUI.showWaiting("正在保存信息");
const writeDataTemp = JSON.stringify(writeData, null,
"\r").replace(/[\r]/g, "");
writer.write(writeDataTemp); // 整个文件重写
writer.onerror = function() {
//console.log("4写入文件失败", writer.error.message);
plus.nativeUI.closeWaiting();
plus.nativeUI.toast("修改信息失败,请重新操作", {
background: "#ffa38c",
});
return;
};
writer.onsuccess = function() { //填写文件成功
plus.nativeUI.closeWaiting();
console.log('填写文件成功')
// plus.nativeUI.toast("填写文件成功", {
// background: "rgba(255, 255, 255, 0.6)",
// });
resolve("1");
};
},
error => {
// console.log("3创建creactWriter失败", error);
// plus.nativeUI.toast("保存文件失败,请重新操作", {
// background: "#ffa38c",
// });
return;
});
});
},
error => {
// console.log("2获取文件失败", error);
// plus.nativeUI.toast("保存文件失败,请重新操作", {
// background: "#ffa38c",
// });
return;
}
);
}, e => {
//console.log("1请求文件系统失败", e.message);
plus.nativeUI.toast("请求系统失败,请重新操作", {
background: "#ffa38c",
});
return;
});
});
};
async function saveFile(url, file, newfilename) {
let c = await creatDirs(url)
let isokm = moveDirectyOrFile(file, url + "/", newfilename);
return isokm
}
//循环创建目录 url:"_doc/...." _doc开头
async function creatDirs(url) {
let urllist = url.split("/");
console.log(urllist)
//创建文件夹
let u = "";
for (let i = 0; i < urllist.length - 1; i++) {
let j = i;
if (i == 0) {
u = urllist[i];
} else {
u = u + "/" + urllist[i];
}
console.log(i + "-------------------")
console.log(u)
console.log(urllist[j + 1])
await CreateNewDir(u, urllist[j + 1]);
}
}
//重命名目录或文件名
function moveDirectyOrFile(srcUrl, dstUrl, newName) { //srcUrl需要移动的目录或文件,dstUrl要移动到的目标目录(父级)
plus.io.resolveLocalFileSystemURL(srcUrl, function(srcEntry) {
//console.log(111)
plus.io.resolveLocalFileSystemURL(dstUrl, function(dstEntry) {
//console.log(222)
if (srcEntry.isDirectory) {
//console.log(33)
srcEntry.moveTo(dstEntry, newName, function(entry) {
//console.log("New Path: " + entry.fullPath);
return true;
}, function(e) {
return e;
//console.log(e.message);
});
} else {
srcEntry.moveTo(dstEntry, newName, function(entry) {
//console.log("New Path: " + entry.fullPath);
return true;
}, function(e) {
return e;
//console.log(e.message);
});
}
}, function(e) {
uni.showToast({
title: '获取目标目录失败:' + e.message,
duration: 2000,
icon: 'none'
});
});
}, function(e) {
uni.showToast({
title: '获取目录失败:' + e.message,
duration: 2000,
icon: 'none'
});
});
}
//创建一个新目录
function CreateNewDir(url, dirName) {
//url值可支持相对路径URL、本地路径URL
return new Promise((resolver, reject) => {
plus.io.resolveLocalFileSystemURL(url, function(entry) {
entry.getDirectory(dirName, {
create: true,
exclusive: false
}, function(dir) {
resolver(true)
}, function(error) {
reject(error.message)
uni.showToast({
title: dirName + '目录创建失败:' + error.message,
duration: 2000,
icon: 'none'
});
});
}, function(e) {
reject(error.message)
uni.showToast({
title: '获取目录失败:' + e.message,
duration: 2000,
icon: 'none'
});
});
})
}
function copyFileTo(url, newUrl, dirName, newName) {
if (url.length >= 7 && "file://" == url.substring(0, 7)) {
url = url.substring(7)
}
let tempUrl = url.substring(0, url.lastIndexOf('/'));
let addUrl = newUrl + '/' + dirName;
console.log(addUrl, tempUrl)
if (addUrl == tempUrl) {
return url;
}
console.log(newUrl, dirName, newName)
return new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(url, async (entry) => {
if (entry.isFile) {
let c = await CreateNewDir(newUrl, dirName)
let u = await getDirsys(addUrl)
entry.copyTo(u, newName, en => {
resolve(en.fullPath);
}, e => {
console.log(e);
reject('错误:复制时出现错误')
uni.showModal({
title: "错误",
content: "复制时出现错误"
})
})
} else {
reject('错误:路径必须是文件')
uni.showModal({
title: "错误",
content: "路径必须是文件"
})
}
}, (e) => {
console.log(e);
reject(e)
uni.showModal({
title: "错误",
content: "打开文件系统时出错"
})
});
})
}
//获取目录对象
function getDirsys(url) {
return new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(url, (entry) => {
resolve(entry)
}, (e) => {
reject(e)
console.log(e);
});
})
}
//将这些方法暴露出去
export {
getJsonData,
changeData,
saveFile,
creatDirs,
moveDirectyOrFile,
copyFileTo,
getDirsys,
}
亲测有用,目前没有发现有什么兼容问题,这样就不用担心内存的问题了,使用的是手机内存。