Skip to content

Commit

Permalink
feat: 文件搜索
Browse files Browse the repository at this point in the history
  • Loading branch information
devhaozi committed Oct 20, 2024
1 parent a2ebc07 commit f9233bd
Show file tree
Hide file tree
Showing 10 changed files with 394 additions and 60 deletions.
14 changes: 13 additions & 1 deletion internal/http/request/file.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package request

import (
"net/http"

"github.com/spf13/cast"
)

type FileList struct {
Path string `json:"path" form:"path" validate:"required"`
Sort string `json:"sort" form:"sort"`
Expand Down Expand Up @@ -50,5 +56,11 @@ type FileUnCompress struct {

type FileSearch struct {
Path string `form:"path" json:"path" validate:"required"`
KeyWord string `form:"keyword" json:"keyword" validate:"required"`
Keyword string `form:"keyword" json:"keyword" validate:"required"`
Sub bool `form:"sub" json:"sub"`
}

func (r *FileSearch) Prepare(req *http.Request) error {
r.Sub = cast.ToBool(req.FormValue("sub"))
return nil
}
2 changes: 1 addition & 1 deletion internal/route/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func Http(r chi.Router) {
r.Post("/permission", file.Permission)
r.Post("/compress", file.Compress)
r.Post("/unCompress", file.UnCompress)
r.Post("/search", file.Search)
r.Get("/search", file.Search)
r.Get("/list", file.List)
})

Expand Down
83 changes: 62 additions & 21 deletions internal/service/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"time"

"github.com/go-rat/chix"
"github.com/spf13/cast"

"github.com/TheTNB/panel/internal/http/request"
"github.com/TheTNB/panel/pkg/io"
Expand Down Expand Up @@ -327,22 +328,18 @@ func (s *FileService) Search(w http.ResponseWriter, r *http.Request) {
return
}

paths := make(map[string]stdos.FileInfo)
err = filepath.Walk(req.Path, func(path string, info stdos.FileInfo, err error) error {
if err != nil {
return err
}
if strings.Contains(info.Name(), req.KeyWord) {
paths[path] = info
}
return nil
})
results, err := io.SearchX(req.Path, req.Keyword, req.Sub)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}

Success(w, paths)
paged, total := Paginate(r, s.formatInfo(results))

Success(w, chix.M{
"total": total,
"items": paged,
})
}

func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -378,14 +375,27 @@ func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
})
}

paged, total := Paginate(r, s.formatDir(req.Path, list))

Success(w, chix.M{
"total": total,
"items": paged,
})
}

// formatDir 格式化目录信息
func (s *FileService) formatDir(base string, entries []stdos.DirEntry) []any {
var paths []any
for _, file := range list {
info, _ := file.Info()
stat := info.Sys().(*syscall.Stat_t)
for _, file := range entries {
info, err := file.Info()
if err != nil {
continue
}

stat := info.Sys().(*syscall.Stat_t)
paths = append(paths, map[string]any{
"name": info.Name(),
"full": filepath.Join(req.Path, info.Name()),
"full": filepath.Join(base, info.Name()),
"size": str.FormatBytes(float64(info.Size())),
"mode_str": info.Mode().String(),
"mode": fmt.Sprintf("%04o", info.Mode().Perm()),
Expand All @@ -395,21 +405,52 @@ func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
"gid": stat.Gid,
"hidden": io.IsHidden(info.Name()),
"symlink": io.IsSymlink(info.Mode()),
"link": io.GetSymlink(filepath.Join(req.Path, info.Name())),
"link": io.GetSymlink(filepath.Join(base, info.Name())),
"dir": info.IsDir(),
"modify": info.ModTime().Format(time.DateTime),
})
}

paged, total := Paginate(r, paths)
return paths
}

Success(w, chix.M{
"total": total,
"items": paged,
// formatInfo 格式化文件信息
func (s *FileService) formatInfo(infos map[string]stdos.FileInfo) []map[string]any {
var paths []map[string]any
for path, info := range infos {
stat := info.Sys().(*syscall.Stat_t)
paths = append(paths, map[string]any{
"name": info.Name(),
"full": path,
"size": str.FormatBytes(float64(info.Size())),
"mode_str": info.Mode().String(),
"mode": fmt.Sprintf("%04o", info.Mode().Perm()),
"owner": os.GetUser(stat.Uid),
"group": os.GetGroup(stat.Gid),
"uid": stat.Uid,
"gid": stat.Gid,
"hidden": io.IsHidden(info.Name()),
"symlink": io.IsSymlink(info.Mode()),
"link": io.GetSymlink(path),
"dir": info.IsDir(),
"modify": info.ModTime().Format(time.DateTime),
})
}

slices.SortFunc(paths, func(a, b map[string]any) int {
if cast.ToBool(a["dir"]) && !cast.ToBool(b["dir"]) {
return -1
}
if !cast.ToBool(a["dir"]) && cast.ToBool(b["dir"]) {
return 1
}
return strings.Compare(strings.ToLower(cast.ToString(a["name"])), strings.ToLower(cast.ToString(b["name"])))
})

return paths
}

// setPermission
// setPermission 设置权限
func (s *FileService) setPermission(path string, mode stdos.FileMode, owner, group string) {
_ = io.Chmod(path, mode)
_ = io.Chown(path, owner, group)
Expand Down
73 changes: 55 additions & 18 deletions internal/service/file_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"time"

"github.com/go-rat/chix"
"github.com/spf13/cast"

"github.com/TheTNB/panel/internal/http/request"
"github.com/TheTNB/panel/pkg/io"
Expand Down Expand Up @@ -314,22 +315,18 @@ func (s *FileService) Search(w http.ResponseWriter, r *http.Request) {
return
}

paths := make(map[string]stdos.FileInfo)
err = filepath.Walk(req.Path, func(path string, info stdos.FileInfo, err error) error {
if err != nil {
return err
}
if strings.Contains(info.Name(), req.KeyWord) {
paths[path] = info
}
return nil
})
results, err := io.SearchX(req.Path, req.Keyword, req.Sub)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}

Success(w, paths)
paged, total := Paginate(r, s.formatInfo(results))

Success(w, chix.M{
"total": total,
"items": paged,
})
}

func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -365,13 +362,23 @@ func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
})
}

paged, total := Paginate(r, s.formatDir(req.Path, list))

Success(w, chix.M{
"total": total,
"items": paged,
})
}

// formatDir 格式化目录信息
func (s *FileService) formatDir(base string, entries []stdos.DirEntry) []any {
var paths []any
for _, file := range list {
for _, file := range entries {
info, _ := file.Info()

paths = append(paths, map[string]any{
"name": info.Name(),
"full": filepath.Join(req.Path, info.Name()),
"full": filepath.Join(base, info.Name()),
"size": str.FormatBytes(float64(info.Size())),
"mode_str": info.Mode().String(),
"mode": fmt.Sprintf("%04o", info.Mode().Perm()),
Expand All @@ -381,18 +388,48 @@ func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
"gid": 0,
"hidden": io.IsHidden(info.Name()),
"symlink": io.IsSymlink(info.Mode()),
"link": io.GetSymlink(filepath.Join(req.Path, info.Name())),
"link": io.GetSymlink(filepath.Join(base, info.Name())),
"dir": info.IsDir(),
"modify": info.ModTime().Format(time.DateTime),
})
}

paged, total := Paginate(r, paths)
return paths
}

Success(w, chix.M{
"total": total,
"items": paged,
// formatInfo 格式化文件信息
func (s *FileService) formatInfo(infos map[string]stdos.FileInfo) []map[string]any {
var paths []map[string]any
for path, info := range infos {
paths = append(paths, map[string]any{
"name": info.Name(),
"full": path,
"size": str.FormatBytes(float64(info.Size())),
"mode_str": info.Mode().String(),
"mode": fmt.Sprintf("%04o", info.Mode().Perm()),
"owner": "",
"group": "",
"uid": 0,
"gid": 0,
"hidden": io.IsHidden(info.Name()),
"symlink": io.IsSymlink(info.Mode()),
"link": io.GetSymlink(path),
"dir": info.IsDir(),
"modify": info.ModTime().Format(time.DateTime),
})
}

slices.SortFunc(paths, func(a, b map[string]any) int {
if cast.ToBool(a["dir"]) && !cast.ToBool(b["dir"]) {
return -1
}
if !cast.ToBool(a["dir"]) && cast.ToBool(b["dir"]) {
return 1
}
return strings.Compare(strings.ToLower(cast.ToString(a["name"])), strings.ToLower(cast.ToString(b["name"])))
})

return paths
}

// setPermission
Expand Down
5 changes: 5 additions & 0 deletions pkg/io/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ func GetSymlink(path string) string {
return linkPath
}

// TempFile 创建临时文件
func TempFile(dir, prefix string) (*os.File, error) {
return os.CreateTemp(dir, prefix)
}

func getFormat(f FormatArchive) archiver.CompressedArchive {
format := archiver.CompressedArchive{}
switch f {
Expand Down
60 changes: 55 additions & 5 deletions pkg/io/path.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io

import (
"bytes"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -146,11 +147,6 @@ func TempDir(prefix string) (string, error) {
return os.MkdirTemp("", prefix)
}

// TempFile 创建临时文件
func TempFile(dir, prefix string) (*os.File, error) {
return os.CreateTemp(dir, prefix)
}

// ReadDir 读取目录
func ReadDir(path string) ([]os.DirEntry, error) {
return os.ReadDir(path)
Expand Down Expand Up @@ -190,3 +186,57 @@ func CountX(path string) (int64, error) {
count := len(string(out))
return int64(count), nil
}

// Search 查找文件/文件夹
func Search(path, keyword string, sub bool) (map[string]os.FileInfo, error) {
paths := make(map[string]os.FileInfo)
baseDepth := strings.Count(filepath.Clean(path), string(os.PathSeparator))

err := filepath.Walk(path, func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !sub && strings.Count(p, string(os.PathSeparator)) > baseDepth+1 {
return filepath.SkipDir
}
if strings.Contains(info.Name(), keyword) {
paths[p] = info
}
return nil
})

return paths, err
}

// SearchX 查找文件/文件夹(find命令)
func SearchX(path, keyword string, sub bool) (map[string]os.FileInfo, error) {
paths := make(map[string]os.FileInfo)

var cmd *exec.Cmd
if sub {
cmd = exec.Command("find", path, "-name", "*"+keyword+"*")
} else {
cmd = exec.Command("find", path, "-maxdepth", "1", "-name", "*"+keyword+"*")
}
var out bytes.Buffer
cmd.Stdout = &out

if err := cmd.Run(); err != nil {
return nil, err
}

lines := strings.Split(out.String(), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
info, err := os.Stat(line)
if err != nil {
return nil, err
}
paths[line] = info
}

return paths, nil
}
10 changes: 8 additions & 2 deletions web/src/api/panel/file/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,14 @@ export default {
unCompress: (file: string, path: string): Promise<AxiosResponse<any>> =>
request.post('/file/unCompress', { file, path }),
// 搜索文件
search: (keyword: string): Promise<AxiosResponse<any>> =>
request.post('/file/search', { keyword }),
search: (
path: string,
keyword: string,
sub: boolean,
page: number,
limit: number
): Promise<AxiosResponse<any>> =>
request.get('/file/search', { params: { path, keyword, sub, page, limit } }),
// 获取文件列表
list: (path: string, page: number, limit: number, sort: string): Promise<AxiosResponse<any>> =>
request.get('/file/list', { params: { path, page, limit, sort } })
Expand Down
Loading

0 comments on commit f9233bd

Please sign in to comment.