uniapp开发的app原生操作手机系统文件

项目中有这么一个需求,要求不调后台接口,但是前端要有增删改的操作,这个时候可能会想到用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,
}

亲测有用,目前没有发现有什么兼容问题,这样就不用担心内存的问题了,使用的是手机内存。

相关推荐
小蜜蜂嗡嗡2 小时前
【flutter对屏幕底部有手势区域(如:一条横杠)导致出现重叠遮挡】
前端·javascript·flutter
伍哥的传说3 小时前
Vue 3 useModel vs defineModel:选择正确的双向绑定方案
前端·javascript·vue.js·definemodel对比·usemodel教程·vue3.4新特性·vue双向绑定
小付-小付4 小时前
萤石云监控web+uniapp
uni-app
胡gh8 小时前
页面卡成PPT?重排重绘惹的祸!依旧性能优化
前端·javascript·面试
胡gh8 小时前
简单又复杂,难道只能说一个有箭头一个没箭头?这种问题该怎么回答?
javascript·后端·面试
言兴8 小时前
# 深度解析 ECharts:从零到一构建企业级数据可视化看板
前端·javascript·面试
山有木兮木有枝_8 小时前
TailWind CSS
前端·css·postcss
烛阴9 小时前
TypeScript 的“读心术”:让类型在代码中“流动”起来
前端·javascript·typescript
杨荧9 小时前
基于Python的农作物病虫害防治网站 Python+Django+Vue.js
大数据·前端·vue.js·爬虫·python
Moment10 小时前
毕业一年了,分享一下我的四个开源项目!😊😊😊
前端·后端·开源