mirror of
https://github.com/cloudreve/Cloudreve.git
synced 2024-04-21 12:31:40 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e5683bc3b | ||
|
|
a31ac2299a | ||
|
|
3b16d7d77c | ||
|
|
8ab0fe0e2f | ||
|
|
d51351eebd | ||
|
|
6af1eeb9fb | ||
|
|
94507fe609 | ||
|
|
1038bae238 |
+1
-1
Submodule assets updated: c4a7dfea2c...2d20892994
+8
-3
@@ -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
|
||||
@@ -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
|
||||
@@ -143,7 +148,7 @@ func GetFilesByKeywords(uid uint, keywords ...interface{}) ([]File, error) {
|
||||
|
||||
// GetChildFilesOfFolders 批量检索目录子文件
|
||||
func GetChildFilesOfFolders(folders *[]Folder) ([]File, error) {
|
||||
// 将所有待删除目录ID抽离,以便检索文件
|
||||
// 将所有待检索目录ID抽离,以便检索文件
|
||||
folderIDs := make([]uint, 0, len(*folders))
|
||||
for _, value := range *folders {
|
||||
folderIDs = append(folderIDs, value.ID)
|
||||
|
||||
+11
-2
@@ -561,7 +561,7 @@ func TestGetFilesByKeywords(t *testing.T) {
|
||||
// 未指定用户
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)").WithArgs("k1", "k2").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
res, err := GetFilesByKeywords(0, "k1", "k2")
|
||||
res, err := GetFilesByKeywords(0, nil, "k1", "k2")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.NoError(err)
|
||||
asserts.Len(res, 1)
|
||||
@@ -570,7 +570,16 @@ func TestGetFilesByKeywords(t *testing.T) {
|
||||
// 指定用户
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)").WithArgs(1, "k1", "k2").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
res, err := GetFilesByKeywords(1, "k1", "k2")
|
||||
res, err := GetFilesByKeywords(1, nil, "k1", "k2")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.NoError(err)
|
||||
asserts.Len(res, 1)
|
||||
}
|
||||
|
||||
// 指定父目录
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)").WithArgs(1, 12, "k1", "k2").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
res, err := GetFilesByKeywords(1, []uint{12}, "k1", "k2")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.NoError(err)
|
||||
asserts.Len(res, 1)
|
||||
|
||||
@@ -31,6 +31,8 @@ type GroupOption struct {
|
||||
ShareDownload bool `json:"share_download,omitempty"`
|
||||
Aria2 bool `json:"aria2,omitempty"` // 离线下载
|
||||
Aria2Options map[string]interface{} `json:"aria2_options,omitempty"` // 离线下载用户组配置
|
||||
SourceBatchSize int `json:"source_batch,omitempty"`
|
||||
Aria2BatchSize int `json:"aria2_batch,omitempty"`
|
||||
}
|
||||
|
||||
// GetGroupByID 用ID获取用户组
|
||||
|
||||
+5
-1
@@ -108,6 +108,8 @@ func addDefaultGroups() {
|
||||
ArchiveTask: true,
|
||||
ShareDownload: true,
|
||||
Aria2: true,
|
||||
SourceBatchSize: 1000,
|
||||
Aria2BatchSize: 50,
|
||||
},
|
||||
}
|
||||
if err := DB.Create(&defaultAdminGroup).Error; err != nil {
|
||||
@@ -126,7 +128,9 @@ func addDefaultGroups() {
|
||||
ShareEnabled: true,
|
||||
WebDAVEnabled: true,
|
||||
OptionsSerialized: GroupOption{
|
||||
ShareDownload: true,
|
||||
ShareDownload: true,
|
||||
SourceBatchSize: 10,
|
||||
Aria2BatchSize: 1,
|
||||
},
|
||||
}
|
||||
if err := DB.Create(&defaultAdminGroup).Error; err != nil {
|
||||
|
||||
@@ -63,6 +63,7 @@ type PolicyOption struct {
|
||||
PlaceholderWithSize bool `json:"placeholder_with_size,omitempty"`
|
||||
}
|
||||
|
||||
// thumbSuffix 支持缩略图处理的文件扩展名
|
||||
var thumbSuffix = map[string][]string{
|
||||
"local": {},
|
||||
"qiniu": {".psd", ".jpg", ".jpeg", ".png", ".gif", ".webp", ".tiff", ".bmp"},
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
package conf
|
||||
|
||||
// BackendVersion 当前后端版本号
|
||||
var BackendVersion = "3.5.2"
|
||||
var BackendVersion = "3.5.3"
|
||||
|
||||
// RequiredDBVersion 与当前版本匹配的数据库版本
|
||||
var RequiredDBVersion = "3.5.2"
|
||||
|
||||
// RequiredStaticVersion 与当前版本匹配的静态资源版本
|
||||
var RequiredStaticVersion = "3.5.2"
|
||||
var RequiredStaticVersion = "3.5.3"
|
||||
|
||||
// IsPro 是否为Pro版本
|
||||
var IsPro = "false"
|
||||
|
||||
+16
-1
@@ -2,6 +2,7 @@ package filesystem
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
@@ -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
|
||||
|
||||
@@ -284,6 +284,10 @@ func HookPopPlaceholderToFile(picInfo string) Hook {
|
||||
return func(ctx context.Context, fs *FileSystem, fileHeader fsctx.FileHeader) error {
|
||||
fileInfo := fileHeader.Info()
|
||||
fileModel := fileInfo.Model.(*model.File)
|
||||
if picInfo == "" && fs.Policy.IsThumbExist(fileInfo.FileName) {
|
||||
picInfo = "1,1"
|
||||
}
|
||||
|
||||
return fileModel.PopChunkToFile(fileInfo.LastModified, picInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,6 +671,25 @@ func TestHookPopPlaceholderToFile(t *testing.T) {
|
||||
a.NoError(mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestHookPopPlaceholderToFileBySuffix(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
fs := &FileSystem{
|
||||
Policy: &model.Policy{Type: "cos"},
|
||||
}
|
||||
file := &fsctx.FileStream{
|
||||
Name: "1.png",
|
||||
Model: &model.File{
|
||||
Model: gorm.Model{ID: 1},
|
||||
},
|
||||
}
|
||||
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE(.+)files(.+)").WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectCommit()
|
||||
a.NoError(HookPopPlaceholderToFile("")(context.Background(), fs, file))
|
||||
a.NoError(mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestHookDeleteUploadSession(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
fs := &FileSystem{}
|
||||
|
||||
@@ -80,6 +80,12 @@ const (
|
||||
CodeInvalidChunkIndex = 400012
|
||||
// CodeInvalidContentLength 无效的正文长度
|
||||
CodeInvalidContentLength = 400013
|
||||
// CodeBatchSourceSize 超出批量获取外链限制
|
||||
CodeBatchSourceSize = 40014
|
||||
// CodeBatchAria2Size 超出最大 Aria2 任务数量限制
|
||||
CodeBatchAria2Size = 40015
|
||||
// CodeParentNotExist 父目录不存在
|
||||
CodeParentNotExist = 40016
|
||||
// CodeDBError 数据库操作失败
|
||||
CodeDBError = 50001
|
||||
// CodeEncryptError 加密失败
|
||||
|
||||
@@ -76,3 +76,11 @@ func BuildObjectList(parent uint, objects []Object, policy *model.Policy) Object
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Sources 获取外链的结果响应
|
||||
type Sources struct {
|
||||
URL string `json:"url"`
|
||||
Name string `json:"name"`
|
||||
Parent uint `json:"parent"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ type group struct {
|
||||
ShareDownload bool `json:"shareDownload"`
|
||||
CompressEnabled bool `json:"compress"`
|
||||
WebDAVEnabled bool `json:"webdav"`
|
||||
SourceBatchSize int `json:"sourceBatch"`
|
||||
}
|
||||
|
||||
type tag struct {
|
||||
@@ -98,6 +99,7 @@ func BuildUser(user model.User) User {
|
||||
ShareDownload: user.Group.OptionsSerialized.ShareDownload,
|
||||
CompressEnabled: user.Group.OptionsSerialized.ArchiveTask,
|
||||
WebDAVEnabled: user.Group.WebDAVEnabled,
|
||||
SourceBatchSize: user.Group.OptionsSerialized.SourceBatchSize,
|
||||
},
|
||||
Tags: buildTagRes(tags),
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
// AddAria2URL 添加离线下载URL
|
||||
func AddAria2URL(c *gin.Context) {
|
||||
var addService aria2.AddURLService
|
||||
var addService aria2.BatchAddURLService
|
||||
if err := c.ShouldBindJSON(&addService); err == nil {
|
||||
res := addService.Add(c, common.URLTask)
|
||||
c.JSON(200, res)
|
||||
@@ -52,7 +52,7 @@ func AddAria2Torrent(c *gin.Context) {
|
||||
|
||||
if err := c.ShouldBindJSON(&addService); err == nil {
|
||||
addService.URL = res.Data.(string)
|
||||
res := addService.Add(c, common.URLTask)
|
||||
res := addService.Add(c, nil, common.URLTask)
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
|
||||
+17
-32
@@ -3,10 +3,10 @@ package controllers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
|
||||
"net/http"
|
||||
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/request"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||
"github.com/cloudreve/Cloudreve/v3/service/explorer"
|
||||
@@ -102,39 +102,18 @@ func AnonymousPermLink(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetSource 获取文件的外链地址
|
||||
func GetSource(c *gin.Context) {
|
||||
// 创建上下文
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
fs, err := filesystem.NewFileSystemFromContext(c)
|
||||
if err != nil {
|
||||
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
||||
return
|
||||
var service explorer.ItemIDService
|
||||
if err := c.ShouldBindJSON(&service); err == nil {
|
||||
res := service.Sources(ctx, c)
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
defer fs.Recycle()
|
||||
|
||||
// 获取文件ID
|
||||
fileID, ok := c.Get("object_id")
|
||||
if !ok {
|
||||
c.JSON(200, serializer.ParamErr("文件不存在", err))
|
||||
return
|
||||
}
|
||||
|
||||
sourceURL, err := fs.GetSource(ctx, fileID.(uint))
|
||||
if err != nil {
|
||||
c.JSON(200, serializer.Err(serializer.CodeNotSet, err.Error(), err))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, serializer.Response{
|
||||
Code: 0,
|
||||
Data: struct {
|
||||
URL string `json:"url"`
|
||||
}{URL: sourceURL},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// Thumb 获取文件缩略图
|
||||
@@ -383,12 +362,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 创建空白文件
|
||||
|
||||
@@ -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
|
||||
|
||||
+6
-1
@@ -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(),
|
||||
@@ -558,7 +563,7 @@ func InitMasterRouter() *gin.Engine {
|
||||
// 获取缩略图
|
||||
file.GET("thumb/:id", controllers.Thumb)
|
||||
// 取得文件外链
|
||||
file.GET("source/:id", controllers.GetSource)
|
||||
file.POST("source", controllers.GetSource)
|
||||
// 打包要下载的文件
|
||||
file.POST("archive", controllers.Archive)
|
||||
// 创建文件压缩任务
|
||||
|
||||
+59
-5
@@ -14,13 +14,13 @@ import (
|
||||
)
|
||||
|
||||
// AddURLService 添加URL离线下载服务
|
||||
type AddURLService struct {
|
||||
URL string `json:"url" binding:"required"`
|
||||
Dst string `json:"dst" binding:"required,min=1"`
|
||||
type BatchAddURLService struct {
|
||||
URLs []string `json:"url" binding:"required"`
|
||||
Dst string `json:"dst" binding:"required,min=1"`
|
||||
}
|
||||
|
||||
// Add 主机创建新的链接离线下载任务
|
||||
func (service *AddURLService) Add(c *gin.Context, taskType int) serializer.Response {
|
||||
// Add 主机批量创建新的链接离线下载任务
|
||||
func (service *BatchAddURLService) Add(c *gin.Context, taskType int) serializer.Response {
|
||||
// 创建文件系统
|
||||
fs, err := filesystem.NewFileSystemFromContext(c)
|
||||
if err != nil {
|
||||
@@ -38,6 +38,60 @@ func (service *AddURLService) Add(c *gin.Context, taskType int) serializer.Respo
|
||||
return serializer.Err(serializer.CodeNotFound, "存放路径不存在", nil)
|
||||
}
|
||||
|
||||
// 检查批量任务数量
|
||||
limit := fs.User.Group.OptionsSerialized.Aria2BatchSize
|
||||
if limit > 0 && len(service.URLs) > limit {
|
||||
return serializer.Err(serializer.CodeBatchAria2Size, "Exceed aria2 batch size", nil)
|
||||
}
|
||||
|
||||
res := make([]serializer.Response, 0, len(service.URLs))
|
||||
for _, target := range service.URLs {
|
||||
subService := &AddURLService{
|
||||
URL: target,
|
||||
Dst: service.Dst,
|
||||
}
|
||||
|
||||
addRes := subService.Add(c, fs, taskType)
|
||||
res = append(res, addRes)
|
||||
}
|
||||
|
||||
return serializer.Response{Data: res}
|
||||
}
|
||||
|
||||
// AddURLService 添加URL离线下载服务
|
||||
type AddURLService struct {
|
||||
URL string `json:"url" binding:"required"`
|
||||
Dst string `json:"dst" binding:"required,min=1"`
|
||||
}
|
||||
|
||||
// Add 主机创建新的链接离线下载任务
|
||||
func (service *AddURLService) Add(c *gin.Context, fs *filesystem.FileSystem, taskType int) serializer.Response {
|
||||
if fs == nil {
|
||||
var err error
|
||||
// 创建文件系统
|
||||
fs, err = filesystem.NewFileSystemFromContext(c)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||
}
|
||||
defer fs.Recycle()
|
||||
|
||||
// 检查用户组权限
|
||||
if !fs.User.Group.OptionsSerialized.Aria2 {
|
||||
return serializer.Err(serializer.CodeGroupNotAllowed, "当前用户组无法进行此操作", nil)
|
||||
}
|
||||
|
||||
// 存放目录是否存在
|
||||
if exist, _ := fs.IsPathExist(service.Dst); !exist {
|
||||
return serializer.Err(serializer.CodeNotFound, "存放路径不存在", nil)
|
||||
}
|
||||
}
|
||||
|
||||
downloads := model.GetDownloadsByStatusAndUser(0, fs.User.ID, common.Downloading, common.Paused, common.Ready)
|
||||
limit := fs.User.Group.OptionsSerialized.Aria2BatchSize
|
||||
if limit > 0 && len(downloads)+1 > limit {
|
||||
return serializer.Err(serializer.CodeBatchAria2Size, "Exceed aria2 batch size", nil)
|
||||
}
|
||||
|
||||
// 创建任务
|
||||
task := &model.Download{
|
||||
Status: common.Ready,
|
||||
|
||||
@@ -173,9 +173,9 @@ func (service *OneDriveCallback) PreProcess(c *gin.Context) serializer.Response
|
||||
actualPath := strings.TrimPrefix(uploadSession.SavePath, "/")
|
||||
isSizeCheckFailed := uploadSession.Size != info.Size
|
||||
|
||||
// SharePoint 会对 Office 文档增加 meta data 导致文件大小不一致,这里增加 100 KB 宽容
|
||||
// SharePoint 会对 Office 文档增加 meta data 导致文件大小不一致,这里增加 1 MB 宽容
|
||||
// See: https://github.com/OneDrive/onedrive-api-docs/issues/935
|
||||
if strings.Contains(fs.Policy.OptionsSerialized.OdDriver, "sharepoint.com") && isSizeCheckFailed && (info.Size > uploadSession.Size) && (info.Size-uploadSession.Size <= 102400) {
|
||||
if strings.Contains(fs.Policy.OptionsSerialized.OdDriver, "sharepoint.com") && isSizeCheckFailed && (info.Size > uploadSession.Size) && (info.Size-uploadSession.Size <= 1048576) {
|
||||
isSizeCheckFailed = false
|
||||
}
|
||||
|
||||
|
||||
@@ -428,3 +428,40 @@ func (service *FileIDService) PutContent(ctx context.Context, c *gin.Context) se
|
||||
Code: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Sources 批量获取对象的外链
|
||||
func (s *ItemIDService) Sources(ctx context.Context, c *gin.Context) serializer.Response {
|
||||
fs, err := filesystem.NewFileSystemFromContext(c)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodePolicyNotAllowed, "无法初始化文件系统", err)
|
||||
}
|
||||
defer fs.Recycle()
|
||||
|
||||
if len(s.Raw().Items) > fs.User.Group.OptionsSerialized.SourceBatchSize {
|
||||
return serializer.Err(serializer.CodeBatchSourceSize, "超出批量获取外链的最大数量限制", err)
|
||||
}
|
||||
|
||||
res := make([]serializer.Sources, 0, len(s.Raw().Items))
|
||||
for _, id := range s.Raw().Items {
|
||||
fs.FileTarget = []model.File{}
|
||||
sourceURL, err := fs.GetSource(ctx, id)
|
||||
if len(fs.FileTarget) > 0 {
|
||||
current := serializer.Sources{
|
||||
URL: sourceURL,
|
||||
Name: fs.FileTarget[0].Name,
|
||||
Parent: fs.FileTarget[0].FolderID,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
current.Error = err.Error()
|
||||
}
|
||||
|
||||
res = append(res, current)
|
||||
}
|
||||
}
|
||||
|
||||
return serializer.Response{
|
||||
Code: 0,
|
||||
Data: res,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 执行搜索
|
||||
@@ -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+"%")
|
||||
|
||||
@@ -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+"%")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user