210 lines
5.7 KiB
Go
210 lines
5.7 KiB
Go
package files
|
||
|
||
import (
|
||
"fmt"
|
||
"godo/libs"
|
||
"io"
|
||
"io/fs"
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// Common response structure
|
||
|
||
type OsFileInfo struct {
|
||
IsFile bool `json:"isFile"`
|
||
IsDir bool `json:"isDirectory"`
|
||
IsSymlink bool `json:"isSymlink"`
|
||
Size int64 `json:"size"`
|
||
ModTime time.Time `json:"modTime"`
|
||
AccessTime time.Time `json:"atime"`
|
||
CreateTime time.Time `json:"birthtime"`
|
||
Mode os.FileMode `json:"mode"`
|
||
Name string `json:"name"` // 文件名
|
||
Path string `json:"path"` // 文件路径
|
||
OldPath string `json:"oldPath"` // 旧的文件路径
|
||
ParentPath string `json:"parentPath"` // 父目录路径
|
||
Content string `json:"content"` // 文件内容
|
||
Ext string `json:"ext"` // 文件扩展名
|
||
Title string `json:"title"` // 文件名(不包含扩展名)
|
||
ID int `json:"id,omitempty"` // 文件ID(可选)
|
||
}
|
||
|
||
// validateFilePath 验证路径不为空
|
||
func validateFilePath(path string) error {
|
||
if path == "" {
|
||
return fmt.Errorf("empty path")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// validateFilePathPair 验证源路径和目标路径不为空
|
||
func validateFilePathPair(src, dst string) error {
|
||
if err := validateFilePath(src); err != nil {
|
||
return err
|
||
}
|
||
if err := validateFilePath(dst); err != nil {
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ReadDir reads a directory and returns a list of files
|
||
func ReadDir(basePath, path string) ([]os.DirEntry, error) {
|
||
fullPath := filepath.Join(basePath, path)
|
||
return os.ReadDir(fullPath)
|
||
}
|
||
|
||
// Stat retrieves file information
|
||
func Stat(basePath, path string) (os.FileInfo, error) {
|
||
fullPath := filepath.Join(basePath, path)
|
||
return os.Stat(fullPath)
|
||
}
|
||
|
||
// Exists checks if a file or directory exists
|
||
func Exists(basePath, path string) bool {
|
||
fullPath := filepath.Join(basePath, path)
|
||
// _, err := os.Stat(fullPath)
|
||
// return err == nil
|
||
return libs.PathExists(fullPath)
|
||
}
|
||
|
||
// ReadFile reads a file's content
|
||
func ReadFile(basePath, path string) ([]byte, error) {
|
||
fullPath := filepath.Join(basePath, path)
|
||
return os.ReadFile(fullPath)
|
||
}
|
||
|
||
// Unlink removes a file
|
||
func Unlink(basePath, path string) error {
|
||
fullPath := filepath.Join(basePath, path)
|
||
return os.Remove(fullPath)
|
||
}
|
||
|
||
// Clear removes the entire filesystem
|
||
func Clear(basePath string) error {
|
||
return os.RemoveAll(basePath)
|
||
}
|
||
|
||
// Rename renames a file
|
||
func Rename(basePath, oldPath, newPath string) error {
|
||
return os.Rename(filepath.Join(basePath, oldPath), filepath.Join(basePath, newPath))
|
||
}
|
||
|
||
// Mkdir creates a directory
|
||
func Mkdir(basePath, dirPath string) error {
|
||
fullPath := filepath.Join(basePath, dirPath)
|
||
return os.MkdirAll(fullPath, 0755)
|
||
}
|
||
|
||
// Rmdir removes a directory
|
||
func Rmdir(basePath, dirPath string) error {
|
||
fullPath := filepath.Join(basePath, dirPath)
|
||
return os.RemoveAll(fullPath)
|
||
}
|
||
|
||
// CopyFile copies a file
|
||
func CopyFile(src, dst string) error {
|
||
sf, err := os.Open(src)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer sf.Close()
|
||
|
||
df, err := os.Create(dst)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer df.Close()
|
||
|
||
_, err = io.Copy(df, sf)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
err = df.Sync()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return df.Close()
|
||
}
|
||
|
||
// WriteFile writes content to a file
|
||
func WriteFile(filePath string, content []byte, perm os.FileMode) error {
|
||
return os.WriteFile(filePath, content, perm)
|
||
}
|
||
|
||
// AppendToFile appends content to a file
|
||
// AppendToFile appends the given content to the specified file.
|
||
// It assumes that 'content' is an io.Reader representing the data to append.
|
||
func AppendToFile(filePath string, content io.Reader) error {
|
||
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0644)
|
||
if err != nil {
|
||
// 文件不存在或打开时发生其他错误
|
||
return err
|
||
}
|
||
defer file.Close()
|
||
|
||
// 将内容写入文件
|
||
if _, err := io.Copy(file, content); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
func Chmod(basePath string, path string, mode os.FileMode) error {
|
||
fullPath := filepath.Join(basePath, path)
|
||
return os.Chmod(fullPath, mode)
|
||
}
|
||
|
||
// GetFileInfo 从fs.DirEntry或路径获取文件信息
|
||
func GetFileInfo(entry interface{}, basePath, parentPath string) (*OsFileInfo, error) {
|
||
var fileInfo os.FileInfo
|
||
var err error
|
||
var filePath string
|
||
|
||
switch v := entry.(type) {
|
||
case fs.DirEntry:
|
||
// 如果传入的是fs.DirEntry
|
||
fileInfo, err = v.Info()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to get file info from DirEntry: %v", err)
|
||
}
|
||
filePath = filepath.Join(basePath, parentPath, fileInfo.Name())
|
||
case string:
|
||
// 如果传入的是路径字符串
|
||
filePath = filepath.Join(basePath, parentPath, v)
|
||
fileInfo, err = os.Stat(filePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to stat file from path: %v", err)
|
||
}
|
||
default:
|
||
return nil, fmt.Errorf("unsupported type provided to GetFileInfo, expected fs.DirEntry or string")
|
||
}
|
||
|
||
osFileInfo := &OsFileInfo{
|
||
Name: fileInfo.Name(),
|
||
Path: filePath, // 根据实际情况调整,可能需要使用之前构造的完整路径filePath
|
||
}
|
||
|
||
// 初始化其他字段,如IsFile, IsDir, Size等
|
||
osFileInfo.ID = 0
|
||
osFileInfo.IsFile = !fileInfo.IsDir()
|
||
osFileInfo.IsDir = fileInfo.IsDir()
|
||
osFileInfo.Size = fileInfo.Size()
|
||
osFileInfo.ModTime = fileInfo.ModTime()
|
||
osFileInfo.AccessTime = fileInfo.ModTime() // 注意:os.FileInfo没有直接提供访问时间,这里用修改时间代替
|
||
osFileInfo.CreateTime = fileInfo.ModTime() // 同上,仅作示例
|
||
osFileInfo.Mode = fileInfo.Mode()
|
||
|
||
osFileInfo.Path = strings.TrimPrefix(filePath, basePath)
|
||
osFileInfo.OldPath = osFileInfo.Path
|
||
osFileInfo.ParentPath = parentPath
|
||
osFileInfo.Title = strings.TrimSuffix(osFileInfo.Name, filepath.Ext(osFileInfo.Name))
|
||
osFileInfo.Ext = strings.TrimPrefix(filepath.Ext(osFileInfo.Name), ".")
|
||
|
||
return osFileInfo, nil
|
||
}
|