2024-07-13 15:44:13 +08:00
|
|
|
|
import fs from 'fs'
|
|
|
|
|
|
import { isEmpty } from 'lodash'
|
|
|
|
|
|
import path from 'path'
|
|
|
|
|
|
const fspromises = fs.promises
|
2024-06-06 13:12:04 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断文件或目录是否存在
|
|
|
|
|
|
* @param {*} path 文件或目录的路径
|
|
|
|
|
|
* @returns true表示存在,false表示不存在
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function CheckFileOrDirExist(path) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
try {
|
|
|
|
|
|
await fspromises.access(path)
|
|
|
|
|
|
return true // 文件或目录存在
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return false // 文件或目录不存在
|
|
|
|
|
|
}
|
2024-06-06 13:12:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-24 13:11:19 +08:00
|
|
|
|
// 检查文件夹是不是存在,不存在的话,创建
|
|
|
|
|
|
export async function CheckFolderExistsOrCreate(folderPath) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
try {
|
|
|
|
|
|
if (!(await CheckFileOrDirExist(folderPath))) {
|
|
|
|
|
|
await fspromises.mkdir(folderPath, { recursive: true })
|
2024-06-24 13:11:19 +08:00
|
|
|
|
}
|
2024-07-13 15:44:13 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw new Error(error)
|
|
|
|
|
|
}
|
2024-06-24 13:11:19 +08:00
|
|
|
|
}
|
2024-07-13 15:44:13 +08:00
|
|
|
|
|
2024-06-24 13:11:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 拼接两个地址,返回拼接后的地址
|
|
|
|
|
|
* @param {*} rootPath 根目录的消息
|
|
|
|
|
|
* @param {*} subPath 子目录的消息
|
2024-07-13 15:44:13 +08:00
|
|
|
|
* @returns
|
2024-06-24 13:11:19 +08:00
|
|
|
|
*/
|
|
|
|
|
|
export function JoinPath(rootPath, subPath) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
// 判断第二个地址是不是存在,不存在返回null,存在返回拼接后的地址
|
|
|
|
|
|
if (subPath && !isEmpty(subPath)) {
|
|
|
|
|
|
return path.resolve(rootPath, subPath)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return null
|
|
|
|
|
|
}
|
2024-06-24 13:11:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-13 15:44:13 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 删除指定的文件中里面所有的文件和文件夹
|
|
|
|
|
|
* @param {*} folderPath 文件夹地址
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function DeleteFolderAllFile(folderPath) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let folderIsExist = await CheckFileOrDirExist(folderPath)
|
|
|
|
|
|
if (!folderIsExist) {
|
|
|
|
|
|
throw new Error('目的文件夹不存在,' + folderPath)
|
|
|
|
|
|
}
|
|
|
|
|
|
// 开始删除
|
|
|
|
|
|
let files = await fspromises.readdir(folderPath)
|
|
|
|
|
|
files.forEach(async (file) => {
|
|
|
|
|
|
const curPath = path.join(folderPath, file)
|
|
|
|
|
|
if ((await fspromises.stat(curPath)).isDirectory()) {
|
|
|
|
|
|
// 判断是不是文件夹
|
|
|
|
|
|
await DeleteFolderAllFile(curPath) // 递归删除文件夹内容
|
|
|
|
|
|
fspromises.rmdir(curPath) // 删除空文件夹
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 删除文件
|
|
|
|
|
|
fspromises.unlink(curPath)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw error
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-24 13:11:19 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 拷贝一个文件或者是文件夹到指定的目标地址
|
|
|
|
|
|
* @param {*} source 源文件或文件夹地址
|
|
|
|
|
|
* @param {*} target 目标文件或文件夹地址
|
|
|
|
|
|
* @param {*} checkParent 是否检查父文件夹是否存在,不存在的话创建,默认false,不检查,不存在直接创建
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function CopyFileOrFolder(source, target, checkParent = false) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 判断源文件或文件夹是不是存在
|
|
|
|
|
|
if (!(await CheckFileOrDirExist(source))) {
|
|
|
|
|
|
throw new Error(`源文件或文件夹不存在: ${source}`)
|
|
|
|
|
|
}
|
|
|
|
|
|
// 判断父文件夹是否存在,不存在创建
|
|
|
|
|
|
const parent_path = path.dirname(target)
|
|
|
|
|
|
let parentIsExist = await CheckFileOrDirExist(parent_path)
|
|
|
|
|
|
if (!parentIsExist) {
|
|
|
|
|
|
if (checkParent) {
|
|
|
|
|
|
throw new Error(`目的文件或文件夹的父文件夹不存在: ${parent_path}`)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
await fspromises.mkdir(parent_path, { recursive: true })
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-24 13:11:19 +08:00
|
|
|
|
|
2024-07-13 15:44:13 +08:00
|
|
|
|
// 判断是不是文件夹
|
|
|
|
|
|
const isDirectory = await IsDirectory(source)
|
|
|
|
|
|
// 复制文件夹的逻辑
|
|
|
|
|
|
async function copyDirectory(source, target) {
|
|
|
|
|
|
// 创建目标文件夹
|
|
|
|
|
|
await fspromises.mkdir(target, { recursive: true })
|
|
|
|
|
|
let entries = await fspromises.readdir(source, { withFileTypes: true })
|
|
|
|
|
|
for (let entry of entries) {
|
|
|
|
|
|
let srcPath = path.join(source, entry.name)
|
|
|
|
|
|
let tgtPath = path.join(target, entry.name)
|
|
|
|
|
|
|
|
|
|
|
|
if (entry.isDirectory()) {
|
|
|
|
|
|
await copyDirectory(srcPath, tgtPath)
|
2024-06-24 13:11:19 +08:00
|
|
|
|
} else {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
await fspromises.copyFile(srcPath, tgtPath)
|
2024-06-24 13:11:19 +08:00
|
|
|
|
}
|
2024-07-13 15:44:13 +08:00
|
|
|
|
}
|
2024-06-24 13:11:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-13 15:44:13 +08:00
|
|
|
|
if (isDirectory) {
|
|
|
|
|
|
// 创建目标文件夹
|
|
|
|
|
|
await copyDirectory(source, target)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 复制文件
|
|
|
|
|
|
await fspromises.copyFile(source, target)
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw error
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-24 13:11:19 +08:00
|
|
|
|
|
2024-06-06 13:12:04 +08:00
|
|
|
|
/** * 判断一个文件地址是不是文件夹
|
|
|
|
|
|
* @param {*} path 输入的文件地址
|
|
|
|
|
|
* @returns true 是 false 不是
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function IsDirectory(path) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const stat = await fspromises.stat(path)
|
|
|
|
|
|
return stat.isDirectory()
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw new Error(`获取文件夹信息失败: ${path}`)
|
|
|
|
|
|
}
|
2024-06-06 13:12:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将文件或者是文件夹备份到指定的文职
|
|
|
|
|
|
* @param {*} source_path 源文件/文件夹地址
|
|
|
|
|
|
* @param {*} target_path 目标文件/文件夹地址
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function BackupFileOrFolder(source_path, target_path) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 判断父文件夹是否存在,不存在创建
|
|
|
|
|
|
const parent_path = path.dirname(target_path)
|
|
|
|
|
|
if (!(await CheckFileOrDirExist(parent_path))) {
|
|
|
|
|
|
await fspromises.mkdir(parent_path, { recursive: true })
|
|
|
|
|
|
}
|
2024-06-06 13:12:04 +08:00
|
|
|
|
|
2024-07-13 15:44:13 +08:00
|
|
|
|
// 判断是不是文件夹
|
|
|
|
|
|
const isDirectory = await IsDirectory(source_path)
|
2024-06-06 13:12:04 +08:00
|
|
|
|
|
2024-07-13 15:44:13 +08:00
|
|
|
|
if (isDirectory) {
|
|
|
|
|
|
// 复制文件夹
|
|
|
|
|
|
await fspromises.rename(source_path, target_path)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 复制文件
|
|
|
|
|
|
await fspromises.copyFile(source, target)
|
2024-06-06 13:12:04 +08:00
|
|
|
|
}
|
2024-07-13 15:44:13 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw new Error(error)
|
|
|
|
|
|
}
|
2024-06-06 13:12:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定的文件夹下面的所有的指定的拓展名的文件
|
|
|
|
|
|
* @param {*} folderPath 文件夹地址
|
|
|
|
|
|
* @param {*} extensions 拓展地址
|
|
|
|
|
|
* @returns 返回文件中指定的后缀文件地址(绝对地址)
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function GetFilesWithExtensions(folderPath, extensions) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 判断当前是不是文件夹
|
|
|
|
|
|
if (!(await IsDirectory(folderPath))) {
|
|
|
|
|
|
throw new Error('输入的不是有效的文件夹地址')
|
2024-06-06 13:12:04 +08:00
|
|
|
|
}
|
2024-07-13 15:44:13 +08:00
|
|
|
|
|
|
|
|
|
|
let entries = await fspromises.readdir(folderPath, { withFileTypes: true })
|
|
|
|
|
|
let files = []
|
|
|
|
|
|
// 使用Promise.all来并行处理所有的stat调用
|
|
|
|
|
|
const fileStats = await Promise.all(
|
|
|
|
|
|
entries.map(async (entry) => {
|
|
|
|
|
|
const entryPath = path.join(folderPath, entry.name)
|
|
|
|
|
|
if (entry.isFile()) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
name: entry.name,
|
|
|
|
|
|
path: entryPath,
|
|
|
|
|
|
isFile: true
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return {
|
|
|
|
|
|
isFile: false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 过滤出文件并且满足扩展名要求的文件
|
|
|
|
|
|
files = fileStats.filter(
|
|
|
|
|
|
(fileStat) =>
|
|
|
|
|
|
fileStat.isFile && extensions.includes(path.extname(fileStat.name).toLowerCase())
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 对files数组进行排序,基于文件名
|
|
|
|
|
|
files.sort((a, b) => a.name.localeCompare(b.name))
|
|
|
|
|
|
|
|
|
|
|
|
// 返回文件名数组(完整的)
|
|
|
|
|
|
return files.map((fileStat) => path.join(folderPath, fileStat.name))
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw new Error(error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|