From 0e62665d7f1039c8d5bb4acc9faf4b01fe35b443 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Thu, 16 Jan 2020 10:11:16 +0800 Subject: [PATCH] Fix: do hard-copy when editing file with soft links --- models/file.go | 5 +++ pkg/filesystem/filesystem.go | 6 ++++ pkg/filesystem/fsctx/context.go | 2 ++ pkg/filesystem/hooks.go | 10 ++++++ pkg/filesystem/oss/handller.go | 54 +++++++++++++++++++++++++++++++++ service/explorer/file.go | 12 +++++++- 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 pkg/filesystem/oss/handller.go diff --git a/models/file.go b/models/file.go index e80567f..759425e 100644 --- a/models/file.go +++ b/models/file.go @@ -168,6 +168,11 @@ func (file *File) UpdateSize(value uint64) error { return DB.Model(&file).Update("size", value).Error } +// UpdateSourceName 更新文件的源文件名 +func (file *File) UpdateSourceName(value string) error { + return DB.Model(&file).Update("source_name", value).Error +} + /* 实现 webdav.FileInfo 接口 */ diff --git a/pkg/filesystem/filesystem.go b/pkg/filesystem/filesystem.go index 83d5e81..906b712 100644 --- a/pkg/filesystem/filesystem.go +++ b/pkg/filesystem/filesystem.go @@ -6,6 +6,7 @@ import ( "github.com/HFO4/cloudreve/pkg/auth" "github.com/HFO4/cloudreve/pkg/conf" "github.com/HFO4/cloudreve/pkg/filesystem/local" + "github.com/HFO4/cloudreve/pkg/filesystem/oss" "github.com/HFO4/cloudreve/pkg/filesystem/qiniu" "github.com/HFO4/cloudreve/pkg/filesystem/remote" "github.com/HFO4/cloudreve/pkg/filesystem/response" @@ -167,6 +168,11 @@ func (fs *FileSystem) dispatchHandler() error { Policy: currentPolicy, } return nil + case "oss": + fs.Handler = oss.Handler{ + Policy: currentPolicy, + } + return nil default: return ErrUnknownPolicyType } diff --git a/pkg/filesystem/fsctx/context.go b/pkg/filesystem/fsctx/context.go index 2005c7b..24f80d7 100644 --- a/pkg/filesystem/fsctx/context.go +++ b/pkg/filesystem/fsctx/context.go @@ -21,4 +21,6 @@ const ( UserCtx // ThumbSizeCtx 缩略图尺寸 ThumbSizeCtx + // OriginSourceNameCtx 原始原文件名 + OriginSourceNameCtx ) diff --git a/pkg/filesystem/hooks.go b/pkg/filesystem/hooks.go index 7035b6b..d30817d 100644 --- a/pkg/filesystem/hooks.go +++ b/pkg/filesystem/hooks.go @@ -177,6 +177,16 @@ func HookGiveBackCapacity(ctx context.Context, fs *FileSystem) error { return nil } +// HookUpdateSourceName 更新文件SourceName +// TODO:测试 +func HookUpdateSourceName(ctx context.Context, fs *FileSystem) error { + originFile, ok := ctx.Value(fsctx.FileModelCtx).(model.File) + if !ok { + return ErrObjectNotExist + } + return originFile.UpdateSourceName(originFile.SourceName) +} + // GenericAfterUpdate 文件内容更新后 func GenericAfterUpdate(ctx context.Context, fs *FileSystem) error { // 更新文件尺寸 diff --git a/pkg/filesystem/oss/handller.go b/pkg/filesystem/oss/handller.go new file mode 100644 index 0000000..450c301 --- /dev/null +++ b/pkg/filesystem/oss/handller.go @@ -0,0 +1,54 @@ +package oss + +import ( + "context" + "errors" + model "github.com/HFO4/cloudreve/models" + "github.com/HFO4/cloudreve/pkg/filesystem/response" + "github.com/HFO4/cloudreve/pkg/serializer" + "io" + "net/url" +) + +// Handler 阿里云OSS策略适配器 +type Handler struct { + Policy *model.Policy +} + +// Get 获取文件 +func (handler Handler) Get(ctx context.Context, path string) (response.RSCloser, error) { + return nil, errors.New("未实现") +} + +// Put 将文件流保存到指定目录 +func (handler Handler) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error { + return errors.New("未实现") +} + +// Delete 删除一个或多个文件, +// 返回未删除的文件,及遇到的最后一个错误 +func (handler Handler) Delete(ctx context.Context, files []string) ([]string, error) { + return []string{}, errors.New("未实现") +} + +// Thumb 获取文件缩略图 +func (handler Handler) Thumb(ctx context.Context, path string) (*response.ContentResponse, error) { + return nil, errors.New("未实现") +} + +// Source 获取外链URL +func (handler Handler) Source( + ctx context.Context, + path string, + baseURL url.URL, + ttl int64, + isDownload bool, + speed int, +) (string, error) { + return "", errors.New("未实现") +} + +// Token 获取上传策略和认证Token +func (handler Handler) Token(ctx context.Context, TTL int64, key string) (serializer.UploadCredential, error) { + return serializer.UploadCredential{}, errors.New("未实现") +} diff --git a/service/explorer/file.go b/service/explorer/file.go index 49b55dd..fb67c05 100644 --- a/service/explorer/file.go +++ b/service/explorer/file.go @@ -268,6 +268,7 @@ func (service *SingleFileService) PutContent(ctx context.Context, c *gin.Context if err != nil { return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) } + uploadCtx := context.WithValue(ctx, fsctx.GinCtx, c) // 取得现有文件 exist, originFile := fs.IsFileExist(service.Path) @@ -275,6 +276,16 @@ func (service *SingleFileService) PutContent(ctx context.Context, c *gin.Context return serializer.Err(404, "文件不存在", nil) } + // 检查此文件是否有软链接 + fileList, err := model.RemoveFilesWithSoftLinks([]model.File{*originFile}) + if err == nil && len(fileList) == 0 { + // 如果包含软连接,应重新生成新文件副本,并更新source_name + originFile.SourceName = fs.GenerateSavePath(uploadCtx, fileData) + fs.Use("AfterUpload", filesystem.HookUpdateSourceName) + fs.Use("AfterUploadCanceled", filesystem.HookUpdateSourceName) + fs.Use("AfterValidateFailed", filesystem.HookUpdateSourceName) + } + // 给文件系统分配钩子 fs.Use("BeforeUpload", filesystem.HookValidateFile) fs.Use("BeforeUpload", filesystem.HookResetPolicy) @@ -288,7 +299,6 @@ func (service *SingleFileService) PutContent(ctx context.Context, c *gin.Context fs.Use("AfterValidateFailed", filesystem.HookGiveBackCapacity) // 执行上传 - uploadCtx := context.WithValue(ctx, fsctx.GinCtx, c) uploadCtx = context.WithValue(uploadCtx, fsctx.FileModelCtx, *originFile) err = fs.Upload(uploadCtx, fileData) if err != nil {