diff --git a/pkg/filesystem/filesystem.go b/pkg/filesystem/filesystem.go index 1786809..8ef232a 100644 --- a/pkg/filesystem/filesystem.go +++ b/pkg/filesystem/filesystem.go @@ -11,8 +11,16 @@ import ( "github.com/gin-gonic/gin" "io" "net/url" + "sync" ) +// FSPool 文件系统资源池 +var FSPool = sync.Pool{ + New: func() interface{} { + return &FileSystem{} + }, +} + // FileHeader 上传来的文件数据处理器 type FileHeader interface { io.Reader @@ -77,12 +85,35 @@ type FileSystem struct { Handler Handler } +// getEmptyFS 从pool中获取新的FileSystem +func getEmptyFS() *FileSystem { + fs := FSPool.Get().(*FileSystem) + return fs +} + +// Recycle 回收FileSystem资源 +func (fs *FileSystem) Recycle() { + fs.reset() + FSPool.Put(fs) +} + +// reset 重设文件系统,以便回收使用 +func (fs *FileSystem) reset() { + fs.User = nil + fs.CleanTargets() + fs.Policy = nil + fs.BeforeUpload = fs.BeforeUpload[:0] + fs.AfterUpload = fs.AfterUpload[:0] + fs.AfterValidateFailed = fs.AfterValidateFailed[:0] + fs.AfterUploadCanceled = fs.AfterUploadCanceled[:0] + fs.BeforeFileDownload = fs.BeforeFileDownload[:0] + fs.Handler = nil +} + // NewFileSystem 初始化一个文件系统 func NewFileSystem(user *model.User) (*FileSystem, error) { - fs := &FileSystem{ - User: user, - } - + fs := getEmptyFS() + fs.User = user // 分配存储策略适配器 err := fs.dispatchHandler() @@ -92,9 +123,8 @@ func NewFileSystem(user *model.User) (*FileSystem, error) { // NewAnonymousFileSystem 初始化匿名文件系统 func NewAnonymousFileSystem() (*FileSystem, error) { - fs := &FileSystem{ - User: &model.User{}, - } + fs := getEmptyFS() + fs.User = &model.User{} // 如果是主机模式下,则为匿名文件系统分配游客用户组 if conf.SystemConfig.Mode == "master" { @@ -182,6 +212,6 @@ func (fs *FileSystem) SetTargetFileByIDs(ids []uint) error { // CleanTargets 清空目标 func (fs *FileSystem) CleanTargets() { - fs.FileTarget = []model.File{} - fs.DirTarget = []model.Folder{} + fs.FileTarget = fs.FileTarget[:0] + fs.DirTarget = fs.DirTarget[:0] } diff --git a/pkg/filesystem/filesystem_test.go b/pkg/filesystem/filesystem_test.go index b3ca42b..6ed6afb 100644 --- a/pkg/filesystem/filesystem_test.go +++ b/pkg/filesystem/filesystem_test.go @@ -133,3 +133,18 @@ func TestNewAnonymousFileSystem(t *testing.T) { asserts.Nil(fs) } } + +func TestFileSystem_Recycle(t *testing.T) { + fs := &FileSystem{ + User: &model.User{}, + Policy: &model.Policy{}, + FileTarget: []model.File{model.File{}}, + DirTarget: []model.Folder{model.Folder{}}, + AfterUpload: []Hook{GenericAfterUpdate}, + } + fs.Recycle() + newFS := getEmptyFS() + if fs != newFS { + t.Error("指针不一致") + } +} diff --git a/pkg/filesystem/remote/handler.go b/pkg/filesystem/remote/handler.go index 34e838c..823636c 100644 --- a/pkg/filesystem/remote/handler.go +++ b/pkg/filesystem/remote/handler.go @@ -38,7 +38,7 @@ func (handler Handler) Delete(ctx context.Context, files []string) ([]string, er // Thumb 获取文件缩略图 func (handler Handler) Thumb(ctx context.Context, path string) (*response.ContentResponse, error) { - return nil, nil + return nil, errors.New("未实现") } // Source 获取外链URL diff --git a/routers/controllers/file.go b/routers/controllers/file.go index 90676e6..2a64b01 100644 --- a/routers/controllers/file.go +++ b/routers/controllers/file.go @@ -75,6 +75,7 @@ func GetSource(c *gin.Context) { c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)) return } + defer fs.Recycle() // 获取文件ID fileID, err := strconv.ParseUint(c.Param("id"), 10, 32) @@ -109,6 +110,7 @@ func Thumb(c *gin.Context) { c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)) return } + defer fs.Recycle() // 获取文件ID fileID, err := strconv.ParseUint(c.Param("id"), 10, 32) @@ -261,6 +263,7 @@ func FileUploadStream(c *gin.Context) { c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)) return } + defer fs.Recycle() // 给文件系统分配钩子 fs.Use("BeforeUpload", filesystem.HookValidateFile) diff --git a/routers/controllers/slave.go b/routers/controllers/slave.go index 575754e..a3b24b4 100644 --- a/routers/controllers/slave.go +++ b/routers/controllers/slave.go @@ -24,6 +24,7 @@ func SlaveUpload(c *gin.Context) { c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)) return } + defer fs.Recycle() fs.Handler = local.Handler{} // 从请求中取得上传策略 diff --git a/service/explorer/directory.go b/service/explorer/directory.go index 5b42576..e932905 100644 --- a/service/explorer/directory.go +++ b/service/explorer/directory.go @@ -19,6 +19,7 @@ func (service *DirectoryService) ListDirectory(c *gin.Context) serializer.Respon if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 上下文 ctx, cancel := context.WithCancel(context.Background()) @@ -43,9 +44,12 @@ func (service *DirectoryService) CreateDirectory(c *gin.Context) serializer.Resp if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() + // 上下文 ctx, cancel := context.WithCancel(context.Background()) defer cancel() + // 创建目录 err = fs.CreateDirectory(ctx, service.Path) if err != nil { diff --git a/service/explorer/file.go b/service/explorer/file.go index 03e3b14..588a652 100644 --- a/service/explorer/file.go +++ b/service/explorer/file.go @@ -39,6 +39,7 @@ func (service *DownloadService) DownloadArchived(ctx context.Context, c *gin.Con if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 查找打包的临时文件 zipPath, exist := cache.Get("archive_" + service.ID) @@ -74,6 +75,7 @@ func (service *FileAnonymousGetService) Download(ctx context.Context, c *gin.Con if err != nil { return serializer.Err(serializer.CodeGroupNotAllowed, err.Error(), err) } + defer fs.Recycle() // 查找文件 err = fs.SetTargetFileByIDs([]uint{service.ID}) @@ -103,6 +105,7 @@ func (service *SingleFileService) CreateDocPreviewSession(ctx context.Context, c if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 获取文件临时下载地址 downloadURL, err := fs.GetDownloadURL(ctx, service.Path, "doc_preview_timeout") @@ -130,6 +133,7 @@ func (service *SingleFileService) CreateDownloadSession(ctx context.Context, c * if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 获取下载地址 downloadURL, err := fs.GetDownloadURL(ctx, service.Path, "download_timeout") @@ -150,6 +154,7 @@ func (service *DownloadService) Download(ctx context.Context, c *gin.Context) se if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 查找打包的临时文件 file, exist := cache.Get("download_" + service.ID) @@ -189,6 +194,7 @@ func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Con if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 获取文件流 rs, err := fs.GetDownloadContent(ctx, service.Path) @@ -230,6 +236,7 @@ func (service *SingleFileService) PutContent(ctx context.Context, c *gin.Context if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 取得现有文件 exist, originFile := fs.IsFileExist(service.Path) diff --git a/service/explorer/objects.go b/service/explorer/objects.go index 243da26..340b5c0 100644 --- a/service/explorer/objects.go +++ b/service/explorer/objects.go @@ -42,6 +42,7 @@ func (service *ItemService) Archive(ctx context.Context, c *gin.Context) seriali if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 检查用户组权限 if !fs.User.Group.OptionsSerialized.ArchiveDownloadEnabled { @@ -91,6 +92,7 @@ func (service *ItemService) Delete(ctx context.Context, c *gin.Context) serializ if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 删除对象 err = fs.Delete(ctx, service.Dirs, service.Items) @@ -111,6 +113,7 @@ func (service *ItemMoveService) Move(ctx context.Context, c *gin.Context) serial if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 移动对象 err = fs.Move(ctx, service.Src.Dirs, service.Src.Items, service.SrcDir, service.Dst) @@ -136,6 +139,7 @@ func (service *ItemMoveService) Copy(ctx context.Context, c *gin.Context) serial if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 复制对象 err = fs.Copy(ctx, service.Src.Dirs, service.Src.Items, service.SrcDir, service.Dst) @@ -161,6 +165,7 @@ func (service *ItemRenameService) Rename(ctx context.Context, c *gin.Context) se if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + defer fs.Recycle() // 重命名对象 err = fs.Rename(ctx, service.Src.Dirs, service.Src.Items, service.NewName)