2021-06-27 21:00:24 +08:00
|
|
|
|
import config from '../config';
|
|
|
|
|
import * as path from 'path';
|
|
|
|
|
import * as fs from 'fs-extra';
|
|
|
|
|
|
|
|
|
|
import ProcessHelper from '../util/ProcesHelper';
|
2022-11-27 20:22:42 +08:00
|
|
|
|
import FileObj from '../entity/vo/FileObj';
|
2022-06-12 13:24:47 +08:00
|
|
|
|
import SavePathDao from '../dao/SavePathDao';
|
2022-11-29 23:02:06 +08:00
|
|
|
|
import SavePath from '../entity/po/SavePath';
|
2023-03-07 00:06:59 +08:00
|
|
|
|
import ErrorHelper from "../util/ErrorHelper";
|
2021-06-27 21:00:24 +08:00
|
|
|
|
|
2022-04-07 16:35:17 +08:00
|
|
|
|
let numberSet = new Set(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
|
|
|
|
|
2021-06-27 21:00:24 +08:00
|
|
|
|
class FileService {
|
2023-03-07 00:06:59 +08:00
|
|
|
|
static async readPath(pathStr: string, showHidden: boolean): Promise<Array<FileObj>> {
|
|
|
|
|
pathStr = decodeURIComponent(pathStr);
|
|
|
|
|
let fileList = [];
|
|
|
|
|
if (pathStr.trim().length == 0) {
|
|
|
|
|
//获取根目录路径
|
|
|
|
|
if (config.isWindows) {
|
|
|
|
|
//windows下
|
|
|
|
|
let std: string = (await ProcessHelper.exec('wmic logicaldisk get caption')).replace('Caption', '');
|
|
|
|
|
fileList = std
|
|
|
|
|
.split('\r\n')
|
|
|
|
|
.filter((item) => item.trim().length > 0)
|
|
|
|
|
.map((item) => item.trim());
|
|
|
|
|
} else {
|
|
|
|
|
//linux下
|
|
|
|
|
pathStr = '/';
|
|
|
|
|
fileList = await fs.readdir(pathStr);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!(fs.pathExists(pathStr))) {
|
|
|
|
|
throw new Error("路径不存在");
|
|
|
|
|
}
|
|
|
|
|
fileList = await fs.readdir(pathStr);
|
|
|
|
|
}
|
|
|
|
|
let folderList: Array<FileObj> = [];
|
|
|
|
|
let files: Array<FileObj> = [];
|
|
|
|
|
for (let index in fileList) {
|
|
|
|
|
try {
|
|
|
|
|
let stat = await fs.stat(path.join(pathStr, fileList[index]));
|
|
|
|
|
if (fileList[index].startsWith('.')) {
|
|
|
|
|
if (showHidden) {
|
|
|
|
|
(stat.isDirectory() ? folderList : files).push(
|
|
|
|
|
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
(stat.isDirectory() ? folderList : files).push(
|
|
|
|
|
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
folderList.sort((a, b) => FileService.compareStr(a.name, b.name)).push(...files.sort((a, b) => FileService.compareStr(a.name, b.name)));
|
|
|
|
|
return folderList;
|
|
|
|
|
}
|
2021-06-27 21:00:24 +08:00
|
|
|
|
|
2023-03-07 00:06:59 +08:00
|
|
|
|
/**
|
|
|
|
|
* 递归读取文件夹下所有的文件
|
|
|
|
|
*/
|
|
|
|
|
static async readRecursion(folders: Array<FileObj>): Promise<Array<FileObj>> {
|
|
|
|
|
let res = [];
|
|
|
|
|
await this.readDirRecursion(res, folders, 1);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2022-04-07 16:35:17 +08:00
|
|
|
|
|
2023-03-07 00:06:59 +08:00
|
|
|
|
private static async readDirRecursion(res: Array<FileObj>, folders: Array<FileObj>, depth: number): Promise<void> {
|
|
|
|
|
if (depth > 10) {
|
|
|
|
|
throw ErrorHelper.Error400("递归读取超过10层,强制结束");
|
|
|
|
|
}
|
|
|
|
|
if (folders == null || folders.length == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (let i in folders) {
|
|
|
|
|
let file = folders[i];
|
|
|
|
|
if (!file.isFolder) {
|
|
|
|
|
res.push(file);
|
|
|
|
|
} else {
|
|
|
|
|
let filePath = path.join(file.path, file.name);
|
|
|
|
|
let temp = (await fs.readdir(filePath)).map(item => {
|
|
|
|
|
let stat = fs.statSync(path.join(filePath, item));
|
|
|
|
|
return new FileObj(item, filePath, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime());
|
|
|
|
|
});
|
|
|
|
|
await FileService.readDirRecursion(res, temp, depth + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-12 13:24:47 +08:00
|
|
|
|
|
2023-03-07 00:06:59 +08:00
|
|
|
|
static async checkExist(pathStr: string) {
|
|
|
|
|
return await fs.pathExists(pathStr);
|
|
|
|
|
}
|
2022-06-12 13:24:47 +08:00
|
|
|
|
|
2023-03-07 00:06:59 +08:00
|
|
|
|
/**
|
|
|
|
|
* 收藏路径
|
|
|
|
|
* @param saveObj
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
static async savePath(saveObj: SavePath) {
|
|
|
|
|
await SavePathDao.addOne(saveObj);
|
|
|
|
|
return saveObj;
|
|
|
|
|
}
|
2022-06-12 13:24:47 +08:00
|
|
|
|
|
2023-03-07 00:06:59 +08:00
|
|
|
|
/**
|
|
|
|
|
* 获取保存列表
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
static async getSaveList() {
|
|
|
|
|
return await SavePathDao.getAll();
|
|
|
|
|
}
|
2022-04-07 16:35:17 +08:00
|
|
|
|
|
2023-03-07 00:06:59 +08:00
|
|
|
|
/**
|
|
|
|
|
* 删除
|
|
|
|
|
* @param id
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
static async deleteOne(id) {
|
|
|
|
|
return await SavePathDao.delete(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 数字字母混合排序
|
|
|
|
|
* @param a str
|
|
|
|
|
* @param b str
|
|
|
|
|
*/
|
|
|
|
|
static compareStr(a: string, b: string) {
|
|
|
|
|
let an = a.length;
|
|
|
|
|
let bn = b.length;
|
|
|
|
|
for (let i = 0; i < an;) {
|
|
|
|
|
let charA = FileService.readChar(a, i, an);
|
|
|
|
|
let charB = FileService.readChar(b, i, bn);
|
|
|
|
|
if (charB.length == 0) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (charA !== charB) {
|
|
|
|
|
//读取字符串不相等说明可以得到排序结果
|
|
|
|
|
//如果都为数字,按照数字的比较方法,否则按照字符串比较
|
|
|
|
|
return numberSet.has(charA.charAt(0)) && numberSet.has(charB.charAt(0)) ? Number(charA) - Number(charB) : charA.localeCompare(charB);
|
|
|
|
|
}
|
|
|
|
|
i += charA.length;
|
|
|
|
|
}
|
|
|
|
|
//排到最后都没分结果说明相等
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 读取字符,如果字符为数字就读取整个数字
|
|
|
|
|
* @param a a
|
|
|
|
|
* @param n 数字长度
|
|
|
|
|
*/
|
|
|
|
|
static readChar(a: string, i: number, n: number) {
|
|
|
|
|
let res = "";
|
|
|
|
|
for (; i < n; i++) {
|
|
|
|
|
let char = a.charAt(i);
|
|
|
|
|
if (numberSet.has(char)) {
|
|
|
|
|
//如果当前字符是数字,添加到结果中
|
|
|
|
|
res += char;
|
|
|
|
|
} else {
|
|
|
|
|
//如果不为数字,但是为第一个字符,直接返回,否则返回res
|
|
|
|
|
if (res.length == 0) {
|
|
|
|
|
return char;
|
|
|
|
|
} else {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* delete batch
|
|
|
|
|
* @param files files
|
|
|
|
|
*/
|
|
|
|
|
static async deleteBatch(files: Array<FileObj>): Promise<void> {
|
|
|
|
|
if (files == null || files.length == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (let i in files) {
|
|
|
|
|
await fs.remove(path.join(files[i].path, files[i].name));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* rename file from source to target
|
|
|
|
|
* @param source sourceFile
|
|
|
|
|
* @param target targetFile
|
|
|
|
|
*/
|
|
|
|
|
static async rename(source: FileObj, target: FileObj): Promise<void> {
|
|
|
|
|
await fs.rename(path.join(source.path, source.name), path.join(target.path, target.name));
|
|
|
|
|
}
|
2021-06-27 21:00:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default FileService;
|