feat(workflow): import files from external storage

This commit is contained in:
Aaron Liu
2025-05-20 10:45:16 +08:00
parent 5d72faf688
commit a10a008ed7
32 changed files with 1071 additions and 609 deletions

View File

@@ -45,26 +45,6 @@ func init() {
gob.Register(ArchiveDownloadSession{})
}
// List 列出从机上的文件
func (service *SlaveListService) List(c *gin.Context) serializer.Response {
//// 创建文件系统
//fs, err := filesystem.NewAnonymousFileSystem()
//if err != nil {
// return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err)
//}
//defer fs.Recycle()
//
//objects, err := fs.Handler.List(context.Background(), service.Path, service.Recursive)
//if err != nil {
// return serializer.ErrDeprecated(serializer.CodeIOFailed, "Cannot list files", err)
//}
//
//res, _ := json.Marshal(objects)
//return serializer.Response{Data: string(res)}
return serializer.Response{}
}
// ArchiveService 文件流式打包下載服务
type (
ArchiveService struct {

View File

@@ -3,6 +3,8 @@ package explorer
import (
"encoding/base64"
"fmt"
"strings"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/cluster/routes"
@@ -14,7 +16,6 @@ import (
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/gin-gonic/gin"
"github.com/samber/lo"
"strings"
)
// SlaveDownloadService 从机文件下載服务
@@ -35,12 +36,6 @@ type SlaveFilesService struct {
Files []string `json:"files" binding:"required,gt=0"`
}
// SlaveListService 从机列表服务
type SlaveListService struct {
Path string `json:"path" binding:"required,min=1,max=65535"`
Recursive bool `json:"recursive"`
}
// SlaveServe serves file content
func (s *EntityDownloadService) SlaveServe(c *gin.Context) error {
dep := dependency.FromContext(c)
@@ -249,3 +244,25 @@ func (service *SlaveDeleteFileService) Delete(c *gin.Context) ([]string, error)
return nil, nil
}
type (
SlaveListParamCtx struct{}
SlaveListService struct {
Path string `uri:"path" binding:"required"`
Recursive bool `uri:"recursive"`
}
)
func (s *SlaveListService) List(c *gin.Context) ([]fs.PhysicalObject, error) {
dep := dependency.FromContext(c)
m := manager.NewFileManager(dep, nil)
defer m.Recycle()
d := m.LocalDriver(nil)
objects, err := d.List(c, s.Path, func(i int) {}, s.Recursive)
if err != nil {
return nil, fmt.Errorf("failed to list files: %w", err)
}
return objects, nil
}

View File

@@ -2,6 +2,7 @@ package explorer
import (
"encoding/gob"
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
"time"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
@@ -258,6 +259,57 @@ func (service *ArchiveWorkflowService) CreateCompressTask(c *gin.Context) (*Task
return BuildTaskResponse(t, nil, hasher), nil
}
type (
ImportWorkflowService struct {
Src string `json:"src" binding:"required"`
Dst string `json:"dst" binding:"required"`
ExtractMediaMeta bool `json:"extract_media_meta"`
UserID string `json:"user_id" binding:"required"`
Recursive bool `json:"recursive"`
PolicyID int `json:"policy_id" binding:"required"`
}
CreateImportParamCtx struct{}
)
func (service *ImportWorkflowService) CreateImportTask(c *gin.Context) (*TaskResponse, error) {
dep := dependency.FromContext(c)
user := inventory.UserFromContext(c)
hasher := dep.HashIDEncoder()
m := manager.NewFileManager(dep, user)
defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Only admin can import files", nil)
}
userId, err := hasher.Decode(service.UserID, hashid.UserID)
if err != nil {
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid user id", err)
}
owner, err := dep.UserClient().GetLoginUserByID(c, userId)
if err != nil || owner.ID == 0 {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user", err)
}
dst, err := fs.NewUriFromString(fs.NewMyUri(service.UserID))
if err != nil {
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid destination", err)
}
// Create task
t, err := workflows.NewImportTask(c, owner, service.Src, service.Recursive, dst.Join(service.Dst).String(), service.PolicyID)
if err != nil {
return nil, serializer.NewError(serializer.CodeCreateTaskError, "Failed to create task", err)
}
if err := dep.IoIntenseQueue(c).QueueTask(c, t); err != nil {
return nil, serializer.NewError(serializer.CodeCreateTaskError, "Failed to queue task", err)
}
return BuildTaskResponse(t, nil, hasher), nil
}
type (
ListTaskService struct {
PageSize int `form:"page_size" binding:"required,min=10,max=100"`
@@ -279,7 +331,7 @@ func (service *ListTaskService) ListTasks(c *gin.Context) (*TaskListResponse, er
PageToken: service.NextPageToken,
PageSize: service.PageSize,
},
Types: []string{queue.CreateArchiveTaskType, queue.ExtractArchiveTaskType, queue.RelocateTaskType},
Types: []string{queue.CreateArchiveTaskType, queue.ExtractArchiveTaskType, queue.RelocateTaskType, queue.ImportTaskType},
UserID: user.ID,
}