2024-08-03 12:46:12 +08:00

239 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'fs'
import { isEmpty } from 'lodash'
import path from 'path'
const fspromises = fs.promises
/**
* 判断文件或目录是否存在
* @param {*} path 文件或目录的路径
* @returns true表示存在false表示不存在
*/
export async function CheckFileOrDirExist(path) {
try {
await fspromises.access(path)
return true // 文件或目录存在
} catch (error) {
return false // 文件或目录不存在
}
}
// 检查文件夹是不是存在,不存在的话,创建
export async function CheckFolderExistsOrCreate(folderPath) {
try {
if (!(await CheckFileOrDirExist(folderPath))) {
await fspromises.mkdir(folderPath, { recursive: true })
}
} catch (error) {
throw new Error(error)
}
}
/**
* 拼接两个地址,返回拼接后的地址
* @param {*} rootPath 根目录的消息
* @param {*} subPath 子目录的消息
* @returns
*/
export function JoinPath(rootPath: string, subPath: string): string {
// 判断第二个地址是不是存在不存在返回null存在返回拼接后的地址
if (subPath && !isEmpty(subPath)) {
return path.resolve(rootPath, subPath)
} else {
return null
}
}
/**
* 删除指定的文件中里面所有的文件和文件夹
* @param {*} folderPath 文件夹地址
* @param {*} isDeleteOut 是否删除最外层的文件夹默认false不删除
*/
export async function DeleteFolderAllFile(folderPath: string, isDeleteOut: boolean = false): Promise<void> {
try {
let folderIsExist = await CheckFileOrDirExist(folderPath)
if (!folderIsExist) {
throw new Error('目的文件夹不存在,' + folderPath)
}
// 开始删除
let files = await fspromises.readdir(folderPath)
for (const file of files) {
const curPath = path.join(folderPath, file);
const stat = await fspromises.stat(curPath);
if (stat.isDirectory()) {
// 判断是不是文件夹
await DeleteFolderAllFile(curPath); // 递归删除文件夹内容
await fspromises.rmdir(curPath); // 删除空文件夹
} else {
// 删除文件
await fspromises.unlink(curPath);
}
}
// 判断是不是要删除最外部的文件夹
if (isDeleteOut) {
await fspromises.rmdir(folderPath)
}
} catch (error) {
throw error
}
}
/**
* 拷贝一个文件或者是文件夹到指定的目标地址
* @param {*} source 源文件或文件夹地址
* @param {*} target 目标文件或文件夹地址
* @param {*} checkParent 是否检查父文件夹是否存在不存在的话创建默认false不检查不存在直接创建
*/
export async function CopyFileOrFolder(source, target, checkParent = false) {
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 })
}
}
// 判断是不是文件夹
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)
} else {
await fspromises.copyFile(srcPath, tgtPath)
}
}
}
if (isDirectory) {
// 创建目标文件夹
await copyDirectory(source, target)
} else {
// 复制文件
await fspromises.copyFile(source, target)
}
} catch (error) {
throw error
}
}
/** * 判断一个文件地址是不是文件夹
* @param {*} path 输入的文件地址
* @returns true 是 false 不是
*/
export async function IsDirectory(path) {
try {
const stat = await fspromises.stat(path)
return stat.isDirectory()
} catch (error) {
throw new Error(`获取文件夹信息失败: ${path}`)
}
}
/**
* 将文件或者是文件夹备份到指定的文职
* @param {*} source_path 源文件/文件夹地址
* @param {*} target_path 目标文件/文件夹地址
*/
export async function BackupFileOrFolder(source_path: string, target_path: string): Promise<void> {
try {
// 判断父文件夹是否存在,不存在创建
const parent_path = path.dirname(target_path)
if (!(await CheckFileOrDirExist(parent_path))) {
await fspromises.mkdir(parent_path, { recursive: true })
}
// 判断是不是文件夹
const isDirectory = await IsDirectory(source_path)
if (isDirectory) {
// 复制文件夹
await fspromises.rename(source_path, target_path)
} else {
// 复制文件
await fspromises.copyFile(source_path, target_path)
}
} catch (error) {
throw new Error(error)
}
}
/**
* 获取指定的文件夹下面的所有的指定的拓展名的文件
* @param {*} folderPath 文件夹地址
* @param {*} extensions 拓展地址
* @returns 返回文件中指定的后缀文件地址(绝对地址)
*/
export async function GetFilesWithExtensions(folderPath: string, extensions: string[]): Promise<string[]> {
try {
// 判断当前是不是文件夹
if (!(await IsDirectory(folderPath))) {
throw new Error('输入的不是有效的文件夹地址')
}
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)
}
}
/**
* 获取文件的大小
* @param filePath 文件的地址
* @returns 返回的文件大小为 kb单位
*/
export async function GetFileSize(filePath: string): Promise<number> {
try {
if (!(await CheckFileOrDirExist(filePath))) {
throw new Error("获取文件大小,指定的文件不存在");
}
const stats = await fspromises.stat(filePath);
return stats.size / 1024
} catch (error) {
throw error
}
}