当前位置:   article > 正文

uniapp中IO模块(管理本地文件系统)的常用功能封装_plus.io

plus.io

参考HTML5联盟

IO模块管理本地文件系统,用于对文件系统的目录浏览、文件的读取、文件的写入等操作。通过plus.io可获取文件系统管理对象。

深入uniapp:封装IO模块常用功能以高效管理本地文件系统

在移动应用开发过程中,对本地文件系统的操作是非常常见的需求。uniapp 作为一个使用 Vue.js 开发所有前端应用的框架,可以编译到iOS、Android、H5以及各种小程序等多个平台,其内置的IO模块提供了丰富的API来满足开发者对本地文件系统的操作需求。

本文将详细介绍如何在 uniapp 中封装IO模块的常用功能,以便更高效、更便捷地管理本地文件系统。

1. 了解uniapp的IO模块

uniapp 的IO模块主要提供了文件的读取、写入、删除、复制、移动等操作。在开始封装之前,我们需要先了解这些API的基本用法。

1.1 文件的读取

使用 uni.readFile 方法可以读取本地文件的内容。这是一个异步操作,需要在回调函数中处理读取到的数据。

uni.readFile({
    filePath: 'path/to/file', // 文件的路径
    success: (res) => {
        console.log(res.data); // 读取到的文件内容
    },
    fail: (err) => {
        console.error(err);
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

1.2 文件的写入

uni.writeFile 方法用于写入文件。如果文件不存在,则会创建新文件。

uni.writeFile({
    filePath: 'path/to/file',
    data: 'some data to write',
    success: () => {
        console.log('File written successfully');
    },
    fail: (err) => {
        console.error(err);
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

1.3 文件的删除

使用 uni.removeFile 方法可以删除本地文件。

uni.removeFile({
    filePath: 'path/to/file',
    success: () => {
        console.log('File removed successfully');
    },
    fail: (err) => {
        console.error(err);
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

1.4 文件的复制和移动

uni.copyFileuni.moveFile 方法分别用于复制和移动文件。

// 复制文件
uni.copyFile({
    srcPath: 'path/to/src/file',
    destPath: 'path/to/dest/file',
    success: () => {
        console.log('File copied successfully');
    },
    fail: (err) => {
        console.error(err);
    }
});

// 移动文件
uni.moveFile({
    srcPath: 'path/to/src/file',
    destPath: 'path/to/dest/file',
    success: () => {
        console.log('File moved successfully');
    },
    fail: (err) => {
        console.error(err);
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2. 封装常用功能

了解了IO模块的基本用法后,我们可以开始封装一些常用的功能,以便在项目中重复使用。

2.1 创建一个文件管理工具类

首先,我们可以创建一个文件管理工具类,将所有的文件操作都封装在这个类中。

class FileManager {
    constructor() {
        // 初始化代码(如果有的话)
    }
    
    // 在这里添加文件操作的方法
}

export default new FileManager();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.2 封装读取文件的方法

我们可以在 FileManager 类中添加一个 readFile 方法来封装文件的读取操作。

class FileManager {
    // ...

    readFile(filePath, successCallback, failCallback) {
        uni.readFile({
            filePath: filePath,
            encoding: 'utf8', // 指定读取文件的字符编码
            success: (res) => {
                if (typeof successCallback === 'function') {
                    successCallback(res.data);
                }
            },
            fail: (err) => {
                if (typeof failCallback === 'function') {
                    failCallback(err);
                }
            }
        });
    }

    // ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2.3 封装写入文件的方法

同样地,我们可以在类中添加一个 writeFile 方法来封装文件的写入操作。

class FileManager {
    // ...

    writeFile(filePath, data, successCallback, failCallback) {
        uni.writeFile({
            filePath: filePath,
            data: data,
            encoding: 'utf8', // 指定写入文件的字符编码
            success: () => {
                if (typeof successCallback === 'function') {
                    successCallback();
                }
            },
            fail: (err) => {
                if (typeof failCallback === 'function') {
                    failCallback(err);
                }
            }
        });
    }

    // ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2.4 封装删除、复制和移动文件的方法

用类似的方式,我们可以封装删除、复制和移动文件的方法。

class FileManager {
    // ...

    removeFile(filePath, successCallback, failCallback) {
        uni.removeFile({
            filePath: filePath,
            success: () => {
                if (typeof successCallback === 'function') {
                    successCallback();
                }
            },
            fail: (err) => {
                if (typeof failCallback === 'function') {
                    failCallback(err);
                }
            }
        });
    }

    copyFile(srcPath, destPath, successCallback, failCallback) {
        uni.copyFile({
            srcPath: srcPath,
            destPath: destPath,
            success: () => {
                if (typeof successCallback === 'function') {
                    successCallback();
                }
            },
            fail: (err) => {
                if (typeof failCallback === 'function') {
                    failCallback(err);
                }
            }
        });
    }

    moveFile(srcPath, destPath, successCallback, failCallback) {
        uni.moveFile({
            srcPath: srcPath,
            destPath: destPath,
            success: () => {
                if (typeof successCallback === 'function') {
                    successCallback();
                }
            },
            fail: (err) => {
                if (typeof failCallback === 'function') {
                    failCallback(err);
                }
            }
        });
    }

    // ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

3. 使用封装后的文件管理工具

封装完成后,我们就可以在项目中使用这个文件管理工具了。

import FileManager from './FileManager';

// 读取文件
FileManager.readFile('path/to/file', (data) => {
    console.log(data);
}, (err) => {
    console.error(err);
});

// 写入文件
FileManager.writeFile('path/to/file', 'some data', () => {
    console.log('File written successfully');
}, (err) => {
    console.error(err);
});

// 删除文件
FileManager.removeFile('path/to/file', () => {
    console.log('File removed successfully');
}, (err) => {
    console.error(err);
});

// 复制文件
FileManager.copyFile('path/to/src/file', 'path/to/dest/file', () => {
    console.log('File copied successfully');
}, (err) => {
    console.error(err);
});

// 移动文件
FileManager.moveFile('path/to/src/file', 'path/to/dest/file', () => {
    console.log('File moved successfully');
}, (err) => {
    console.error(err);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

4. 总结

通过封装 uniapp 的IO模块,我们可以更方便、更高效地管理本地文件系统。封装后的文件管理工具类具有良好的可复用性和可扩展性,可以根据项目的实际需求进行进一步的定制和优化。下面是async-await风格的封装:

/**
 * 储存文件到指定的地址:把一个文件移动到另外一个位置 剪切文件 重命名文件
 * @param {String} url				 	新的地址 _doc/ 开头
 * @param {String} file                	原文件地址
 * @param {String} newfilename 			新的文件名
 */
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'
			});
		});
	})
}

/**
 * 获取文件数据
 * @param {String} url 文件路径,最好是相对路径 url:"_doc/...."  _doc开头
 */
function getFileContext(url) {
	return new Promise((resolve, reject) => {
		plus.io.resolveLocalFileSystemURL(url, (entry) => {
			if (entry.isFile) {
				entry.file(function(file) {
					console.log(file);
					const fileReader = new plus.io.FileReader();
					console.log("getFile:" + JSON.stringify(file));
					fileReader.onload = function(evt) {
						console.log(evt);
						resolve(evt.target)
					}
					fileReader.readAsText(file, 'utf-8');
				});
			} else {
				reject('错误:路径必须是文件')
				uni.showModal({
					title: "错误",
					content: "路径必须是文件"
				})
			}
		}, (e) => {
			reject(e)
			uni.showModal({
				title: "错误",
				content: "打开文件系统时出错"
			})
		});
	})
}

/**
 * 复制文件
 * @param {String} url        文件地址,文件路径,最好是相对路径 url:"_doc/...."  _doc开头
 * @param {String} newUrl     目标目录,最好是相对路径 url:"_doc/...."  _doc开头
 * @param {String} newName    拷贝后的文件名称,默认为原始文件名称
 */
function copyFileTo(url, newUrl, newName) {
	let len = arguments.length;
	return new Promise((resolve, reject) => {
		plus.io.resolveLocalFileSystemURL(url, async (entry) => {
			if (entry.isFile) {
				let c = await creatDirs(newUrl)
				let u = await getDirsys(newUrl)
				if (len == 3) {
					entry.copyTo(u, newName, en => {
						console.log(en);
						resolve(en)
					}, e => {
						console.log(e);
						reject('错误:复制时出现错误')
						uni.showModal({
							title: "错误",
							content: "复制时出现错误"
						})
					})
				} else {
					entry.copyTo(u, "", en => {
						console.log(en);
						resolve(en)
					}, e => {
						console.log(JSON.stringify(e));
						reject('错误:复制时出现错误')
						uni.showModal({
							title: "错误",
							content: "复制时出现错误"
						})
					})
				}


			} else {
				reject('错误:路径必须是文件')
				uni.showModal({
					title: "错误",
					content: "路径必须是文件"
				})
			}
		}, (e) => {
			console.log(e);
			reject(e)
			uni.showModal({
				title: "错误",
				content: "打开文件系统时出错"
			})
		});
	})
}

/**
 * 根据条件,获取目录中包含的文件及子目录
 * @param {Object} params {	url:指定的目录,
 * 							type:要列出的是文件file,还是目录dir,还是所有all,
 * 							regex:正则表达式,根据文件或者目录的名称进行筛选
 *  					  }
 * @return {Promise} 返回 列表Array
 */
async function getDirList(params) {
	let url = params.url ?? "_doc"
	let type = params.type ?? "all"
	let regex = params.regex ?? new RegExp("")

	const d = await getDirsys(url)
	return new Promise((resolve, reject) => {
		d.createReader().readEntries(entries => {
			let result = []
			for (let i = 0; i < entries.length; i++) {
				let a = {
					url: entries[i].fullPath,
					name: entries[i].name
				}

				switch (params?.type) {
					case "file": {
						if (entries[i].isFile == true && regex.test(entries[i].name)) {
							result.push(a)
						}
						break;
					}

					case "dir": {
						if (entries[i].isDirectory == true && regex.test(entries[i].name)) {
							result.push(a)
						}
						break;
					}

					case "all": {
						if (regex.test(entries[i].name)) {
							result.push(a)
						}
						break;
					}

					default: {
						if (regex.test(entries[i].name)) {
							result.push(a)
						}
						break;
					}


				}
			}
			// let ul = entries.filter(e=>e.isFile == true)
			// let result = ul.map(e=>{
			// 	return {
			// 		url:e.fullPath,
			// 		name:e.name
			// 	}
			// })
			resolve(result)
		}, e => {
			reject(e)
			uni.showModal({
				title: "错误",
				content: "Read entries failed: " + e.message
			})
		})
	})

}
//删除目录或者文件,如果是目录,将会删除其下的所有文件及子目录
async function remove(url) {
	const d = await getDirsys(url)
	return new Promise((resolve, reject) => {
		if (d.isDirectory) {
			//删除目录将会删除其下的所有文件及子目录 不能删除根目录,如果操作删除根目录将会删除目录下的文件及子目录,不会删除根目录自身
			d.removeRecursively(() => {
				resolve("删除成功")
			}, e => {
				console.log(e);
				uni.showModal({
					title: "删除时错误",
					content: e.message
				})
			})
		}
		if (d.isFile) {
			d.remove(() => {
				resolve("删除成功")
			}, e => {
				console.log(e);
				uni.showModal({
					title: "删除时错误",
					content: e.message
				})
			})
		}
	})
}
/**
 * 写数据
 * @param {Object} url 创建文件的路径,必须是已经存在的路径
 * @param {Object} filename 文件名
 */
function writeFile(url,filename,str) {
	return new Promise((resolve,reject)=>{
		plus.io.requestFileSystem(url, function(fs) {
			// 可通过fs进行文件操作 
			console.log("Request file system success!");
			console.log(fs.name);
			fs.root.getFile(
				filename, {
					create: true,
					exclusive: false
				},
				fileEntry => {
					fileEntry.createWriter(
						writer => {
							writer.onwrite = e => {
								console.log(e.target.fileName);
								resolve(e)
								// setTimeout(function() {
								// 	// that.proshow = false;
								// 	uni.openDocument({
								// 		filePath: `file://${e.target.fileName}`, //这里必须加file://否则会报错打不开文件
								// 		success: function(res) {
								// 			console.log(res);
								// 			resolve(res)
								// 		},
								// 		fail(res) {
								// 			console.log(res);
								// 			reject(res)
								// 		}
								// 	});
								// }, 1000);
							};
							writer.write(str);
						},
						function(e) {
							uni.showToast({
								title: '导出文件失败,请检查你的权限',
								icon: 'none'
							});
							reject(e)
						}
					);
				},
				e => {
					console.log(e);
					reject(e)
				}
		
			);
		
		}, function(e) {
			reject(e)
		});
	})

}


//获取目录对象
function getDirsys(url) {
	return new Promise((resolve, reject) => {
		plus.io.resolveLocalFileSystemURL(url, (entry) => {
			resolve(entry)
		}, (e) => {
			reject(e)
			console.log(e);
		});
	})
}
export default {
	saveFile,
	creatDirs,
	moveDirectyOrFile,
	getFileContext,
	copyFileTo,
	getDirList,
	getDirsys,
	writeFile,
	remove
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读