Skip to content

Commit

Permalink
feat: search file under current folder
Browse files Browse the repository at this point in the history
  • Loading branch information
HFO4 committed Apr 29, 2022
1 parent d51351e commit 8ab0fe0
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 7 deletions.
9 changes: 7 additions & 2 deletions models/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ func GetFilesByIDsFromTX(tx *gorm.DB, ids []uint, uid uint) ([]File, error) {
}

// GetFilesByKeywords 根据关键字搜索文件,
// UID为0表示忽略用户,只根据文件ID检索
func GetFilesByKeywords(uid uint, keywords ...interface{}) ([]File, error) {
// UID为0表示忽略用户,只根据文件ID检索. 如果 parents 非空, 则只限制在 parent 包含的目录下搜索
func GetFilesByKeywords(uid uint, parents []uint, keywords ...interface{}) ([]File, error) {
var (
files []File
result = DB
Expand All @@ -136,6 +136,11 @@ func GetFilesByKeywords(uid uint, keywords ...interface{}) ([]File, error) {
if uid != 0 {
result = result.Where("user_id = ?", uid)
}

if len(parents) > 0 {
result = result.Where("folder_id in (?)", parents)
}

result = result.Where("("+conditions+")", keywords...).Find(&files)

return files, result.Error
Expand Down
17 changes: 16 additions & 1 deletion pkg/filesystem/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package filesystem

import (
"context"
"fmt"
"io"

model "github.com/cloudreve/Cloudreve/v3/models"
Expand Down Expand Up @@ -361,7 +362,21 @@ func (fs *FileSystem) resetPolicyToFirstFile(ctx context.Context) error {

// Search 搜索文件
func (fs *FileSystem) Search(ctx context.Context, keywords ...interface{}) ([]serializer.Object, error) {
files, _ := model.GetFilesByKeywords(fs.User.ID, keywords...)
parents := make([]uint, 0)

// 如果限定了根目录,则只在这个根目录下搜索。
if fs.Root != nil {
allFolders, err := model.GetRecursiveChildFolder([]uint{fs.Root.ID}, fs.User.ID, true)
if err != nil {
return nil, fmt.Errorf("failed to list all folders: %w", err)
}

for _, folder := range allFolders {
parents = append(parents, folder.ID)
}
}

files, _ := model.GetFilesByKeywords(fs.User.ID, parents, keywords...)
fs.SetTargetFile(&files)

return fs.listObjects(ctx, "/", files, nil, nil), nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/serializer/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ const (
CodeBatchSourceSize = 40014
// CodeBatchAria2Size 超出最大 Aria2 任务数量限制
CodeBatchAria2Size = 40012
// CodeParentNotExist 父目录不存在
CodeParentNotExist = 40013
// CodeDBError 数据库操作失败
CodeDBError = 50001
// CodeEncryptError 加密失败
Expand Down
14 changes: 10 additions & 4 deletions routers/controllers/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,18 @@ func GetUploadSession(c *gin.Context) {
// SearchFile 搜索文件
func SearchFile(c *gin.Context) {
var service explorer.ItemSearchService
if err := c.ShouldBindUri(&service); err == nil {
res := service.Search(c)
c.JSON(200, res)
} else {
if err := c.ShouldBindUri(&service); err != nil {
c.JSON(200, ErrorResponse(err))
return
}

if err := c.ShouldBindQuery(&service); err != nil {
c.JSON(200, ErrorResponse(err))
return
}

res := service.Search(c)
c.JSON(200, res)
}

// CreateFile 创建空白文件
Expand Down
17 changes: 17 additions & 0 deletions routers/controllers/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,23 @@ func ListSharedFolder(c *gin.Context) {
}
}

// SearchSharedFolder 搜索分享的目录下的对象
func SearchSharedFolder(c *gin.Context) {
var service share.SearchService
if err := c.ShouldBindUri(&service); err != nil {
c.JSON(200, ErrorResponse(err))
return
}

if err := c.ShouldBindQuery(&service); err != nil {
c.JSON(200, ErrorResponse(err))
return
}

res := service.Search(c)
c.JSON(200, res)
}

// ArchiveShare 打包要下载的分享
func ArchiveShare(c *gin.Context) {
var service share.ArchiveService
Expand Down
5 changes: 5 additions & 0 deletions routers/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ func InitMasterRouter() *gin.Engine {
middleware.CheckShareUnlocked(),
controllers.ListSharedFolder,
)
// 分享目录搜索
share.GET("search/:id/:type/:keywords",
middleware.CheckShareUnlocked(),
controllers.SearchSharedFolder,
)
// 归档打包下载
share.POST("archive/:id",
middleware.CheckShareUnlocked(),
Expand Down
10 changes: 10 additions & 0 deletions service/explorer/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type ItemSearchService struct {
Type string `uri:"type" binding:"required"`
Keywords string `uri:"keywords" binding:"required"`
Path string `form:"path"`
}

// Search 执行搜索
Expand All @@ -26,6 +27,15 @@ func (service *ItemSearchService) Search(c *gin.Context) serializer.Response {
}
defer fs.Recycle()

if service.Path != "" {
ok, parent := fs.IsPathExist(service.Path)
if !ok {
return serializer.Err(serializer.CodeParentNotExist, "Cannot find parent folder", nil)
}

fs.Root = parent
}

switch service.Type {
case "keywords":
return service.SearchKeywords(c, fs, "%"+service.Keywords+"%")
Expand Down
47 changes: 47 additions & 0 deletions service/share/visit.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,50 @@ func (service *ArchiveService) Archive(c *gin.Context) serializer.Response {

return subService.Archive(ctx, c)
}

// SearchService 对分享的目录进行搜索
type SearchService struct {
explorer.ItemSearchService
}

// Search 执行搜索
func (service *SearchService) Search(c *gin.Context) serializer.Response {
shareCtx, _ := c.Get("share")
share := shareCtx.(*model.Share)

if !share.IsDir {
return serializer.ParamErr("此分享无法列目录", nil)
}

if service.Path != "" && !path.IsAbs(service.Path) {
return serializer.ParamErr("路径无效", nil)
}

// 创建文件系统
fs, err := filesystem.NewFileSystem(share.Creator())
if err != nil {
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
}
defer fs.Recycle()

// 上下文
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// 重设根目录
fs.Root = share.Source().(*model.Folder)
fs.Root.Name = "/"
if service.Path != "" {
ok, parent := fs.IsPathExist(service.Path)
if !ok {
return serializer.Err(serializer.CodeParentNotExist, "Cannot find parent folder", nil)
}

fs.Root = parent
}

// 分享Key上下文
ctx = context.WithValue(ctx, fsctx.ShareKeyCtx, hashid.HashID(share.ID, hashid.ShareID))

return service.SearchKeywords(c, fs, "%"+service.Keywords+"%")
}

0 comments on commit 8ab0fe0

Please sign in to comment.