From e37e93a7b6f98d8d0e681d8f41a9d20f3b888065 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Sun, 27 Feb 2022 14:04:30 +0800 Subject: [PATCH] Feat: create hidden file when creating upload session --- pkg/filesystem/driver/cos/handler.go | 10 ++---- pkg/filesystem/driver/local/handler.go | 2 +- pkg/filesystem/driver/onedrive/api.go | 2 +- pkg/filesystem/driver/oss/handler.go | 12 ++----- pkg/filesystem/driver/remote/handler.go | 2 +- pkg/filesystem/driver/s3/handler.go | 10 ++---- pkg/filesystem/fsctx/context.go | 4 --- pkg/filesystem/fsctx/stream.go | 7 ++++ pkg/filesystem/hooks.go | 8 ++++- pkg/filesystem/manage.go | 28 ++++++++------- pkg/filesystem/upload.go | 48 +++++++++++++------------ 11 files changed, 64 insertions(+), 69 deletions(-) diff --git a/pkg/filesystem/driver/cos/handler.go b/pkg/filesystem/driver/cos/handler.go index 589c2fd..d97ad80 100644 --- a/pkg/filesystem/driver/cos/handler.go +++ b/pkg/filesystem/driver/cos/handler.go @@ -352,7 +352,7 @@ func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *seria []interface{}{"content-length-range", 0, handler.Policy.MaxSize}) } - res, err := handler.getUploadCredential(ctx, postPolicy, keyTime) + res, err := handler.getUploadCredential(ctx, postPolicy, keyTime, file.GetSavePath()) if err == nil { res.Callback = apiURL res.Key = uploadSession.Key @@ -375,13 +375,7 @@ func (handler Driver) Meta(ctx context.Context, path string) (*MetaData, error) }, nil } -func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, keyTime string) (serializer.UploadCredential, error) { - // 读取上下文中生成的存储路径 - savePath, ok := ctx.Value(fsctx.SavePathCtx).(string) - if !ok { - return serializer.UploadCredential{}, errors.New("无法获取存储路径") - } - +func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, keyTime string, savePath string) (serializer.UploadCredential, error) { // 编码上传策略 policyJSON, err := json.Marshal(policy) if err != nil { diff --git a/pkg/filesystem/driver/local/handler.go b/pkg/filesystem/driver/local/handler.go index b010b10..be1af28 100644 --- a/pkg/filesystem/driver/local/handler.go +++ b/pkg/filesystem/driver/local/handler.go @@ -88,7 +88,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error { dst := util.RelativePath(filepath.FromSlash(file.GetSavePath())) // 如果非 Overwrite,则检查是否有重名冲突 - if file.GetMode() != fsctx.Overwrite { + if file.GetMode() == fsctx.Create { if util.Exists(dst) { util.Log().Warning("物理同名文件已存在或不可用: %s", dst) return errors.New("物理同名文件已存在或不可用") diff --git a/pkg/filesystem/driver/onedrive/api.go b/pkg/filesystem/driver/onedrive/api.go index 906c89a..05afb2f 100644 --- a/pkg/filesystem/driver/onedrive/api.go +++ b/pkg/filesystem/driver/onedrive/api.go @@ -260,7 +260,7 @@ func (client *Client) UploadChunk(ctx context.Context, uploadURL string, chunk * func (client *Client) Upload(ctx context.Context, file fsctx.FileHeader) error { // 决定是否覆盖文件 overwrite := "replace" - if file.GetMode() != fsctx.Overwrite { + if file.GetMode() != fsctx.Create { overwrite = "fail" } diff --git a/pkg/filesystem/driver/oss/handler.go b/pkg/filesystem/driver/oss/handler.go index b8fd9e4..b644969 100644 --- a/pkg/filesystem/driver/oss/handler.go +++ b/pkg/filesystem/driver/oss/handler.go @@ -237,7 +237,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error { // 是否允许覆盖 overwrite := true - if file.GetMode() != fsctx.Overwrite { + if file.GetMode() == fsctx.Create { overwrite = false } @@ -424,16 +424,10 @@ func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *seria []interface{}{"content-length-range", 0, handler.Policy.MaxSize}) } - return handler.getUploadCredential(ctx, postPolicy, callbackPolicy, ttl) + return handler.getUploadCredential(ctx, postPolicy, callbackPolicy, ttl, file.GetSavePath()) } -func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, callback CallbackPolicy, TTL int64) (serializer.UploadCredential, error) { - // 读取上下文中生成的存储路径 - savePath, ok := ctx.Value(fsctx.SavePathCtx).(string) - if !ok { - return serializer.UploadCredential{}, errors.New("无法获取存储路径") - } - +func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, callback CallbackPolicy, TTL int64, savePath string) (serializer.UploadCredential, error) { // 处理回调策略 callbackPolicyEncoded := "" if callback.CallbackURL != "" { diff --git a/pkg/filesystem/driver/remote/handler.go b/pkg/filesystem/driver/remote/handler.go index 2451b2e..2120ff0 100644 --- a/pkg/filesystem/driver/remote/handler.go +++ b/pkg/filesystem/driver/remote/handler.go @@ -156,7 +156,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error { // 决定是否要禁用文件覆盖 overwrite := "true" - if file.GetMode() != fsctx.Overwrite { + if file.GetMode() != fsctx.Create { overwrite = "false" } diff --git a/pkg/filesystem/driver/s3/handler.go b/pkg/filesystem/driver/s3/handler.go index e5641de..3671a86 100644 --- a/pkg/filesystem/driver/s3/handler.go +++ b/pkg/filesystem/driver/s3/handler.go @@ -349,7 +349,7 @@ func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *seria } // 生成上传凭证 - return handler.getUploadCredential(ctx, putPolicy, apiURL) + return handler.getUploadCredential(ctx, putPolicy, apiURL, file.GetSavePath()) } // Meta 获取文件信息 @@ -376,13 +376,7 @@ func (handler Driver) Meta(ctx context.Context, path string) (*MetaData, error) } -func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, callback *url.URL) (serializer.UploadCredential, error) { - - // 读取上下文中生成的存储路径和文件大小 - savePath, ok := ctx.Value(fsctx.SavePathCtx).(string) - if !ok { - return serializer.UploadCredential{}, errors.New("无法获取存储路径") - } +func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, callback *url.URL, savePath string) (serializer.UploadCredential, error) { longDate := time.Now().UTC().Format("20060102T150405Z") shortDate := time.Now().UTC().Format("20060102") diff --git a/pkg/filesystem/fsctx/context.go b/pkg/filesystem/fsctx/context.go index b334435..06664b3 100644 --- a/pkg/filesystem/fsctx/context.go +++ b/pkg/filesystem/fsctx/context.go @@ -5,10 +5,6 @@ type key int const ( // GinCtx Gin的上下文 GinCtx key = iota - // SavePathCtx 文件物理路径 - SavePathCtx - // FileHeaderCtx 上传的文件 - FileHeaderCtx // PathCtx 文件或目录的虚拟路径 PathCtx // FileModelCtx 文件数据库模型 diff --git a/pkg/filesystem/fsctx/stream.go b/pkg/filesystem/fsctx/stream.go index 573eef3..0f1fafd 100644 --- a/pkg/filesystem/fsctx/stream.go +++ b/pkg/filesystem/fsctx/stream.go @@ -9,8 +9,10 @@ type WriteMode int const ( Overwrite WriteMode = iota + // Append 只适用于本地策略 Append Create + Nop ) // FileStream 用户传来的文件 @@ -71,6 +73,10 @@ func (file *FileStream) GetSavePath() string { return file.SavePath } +func (file *FileStream) SetSize(size uint64) { + file.Size = size +} + // FileHeader 上传来的文件数据处理器 type FileHeader interface { io.Reader @@ -84,4 +90,5 @@ type FileHeader interface { GetLastModified() time.Time IsHidden() bool GetSavePath() string + SetSize(uint64) } diff --git a/pkg/filesystem/hooks.go b/pkg/filesystem/hooks.go index a6fbbfd..ceb86b7 100644 --- a/pkg/filesystem/hooks.go +++ b/pkg/filesystem/hooks.go @@ -284,7 +284,7 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem, fileHeader fsctx.Fi // 检查文件是否存在 if ok, _ := fs.IsChildFileExist( folder, - ctx.Value(fsctx.FileHeaderCtx).(fsctx.FileHeader).GetFileName(), + fileHeader.GetFileName(), ); ok { return ErrFileExisted } @@ -307,3 +307,9 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem, fileHeader fsctx.Fi return nil } + +// HookClearFileHeaderSize 将FileHeader大小设定为0 +func HookClearFileHeaderSize(ctx context.Context, fs *FileSystem, fileHeader fsctx.FileHeader) error { + fileHeader.SetSize(0) + return nil +} diff --git a/pkg/filesystem/manage.go b/pkg/filesystem/manage.go index 528df08..5feb0d1 100644 --- a/pkg/filesystem/manage.go +++ b/pkg/filesystem/manage.go @@ -350,20 +350,22 @@ func (fs *FileSystem) listObjects(ctx context.Context, parent string, files []mo } } - newFile := serializer.Object{ - ID: hashid.HashID(file.ID, hashid.FileID), - Name: file.Name, - Path: processedPath, - Pic: file.PicInfo, - Size: file.Size, - Type: "file", - Date: file.CreatedAt, - SourceEnabled: file.GetPolicy().IsOriginLinkEnable, - } - if shareKey != "" { - newFile.Key = shareKey + if !file.Hidden { + newFile := serializer.Object{ + ID: hashid.HashID(file.ID, hashid.FileID), + Name: file.Name, + Path: processedPath, + Pic: file.PicInfo, + Size: file.Size, + Type: "file", + Date: file.CreatedAt, + SourceEnabled: file.GetPolicy().IsOriginLinkEnable, + } + if shareKey != "" { + newFile.Key = shareKey + } + objects = append(objects, newFile) } - objects = append(objects, newFile) } return objects diff --git a/pkg/filesystem/upload.go b/pkg/filesystem/upload.go index a4d83ee..3299819 100644 --- a/pkg/filesystem/upload.go +++ b/pkg/filesystem/upload.go @@ -20,10 +20,12 @@ import ( ================ */ +const ( + UploadSessionMetaKey = "upload_session" +) + // Upload 上传文件 func (fs *FileSystem) Upload(ctx context.Context, file *fsctx.FileStream) (err error) { - ctx = context.WithValue(ctx, fsctx.FileHeaderCtx, file) - // 上传前的钩子 err = fs.Trigger(ctx, "BeforeUpload", file) if err != nil { @@ -45,10 +47,12 @@ func (fs *FileSystem) Upload(ctx context.Context, file *fsctx.FileStream) (err e go fs.CancelUpload(ctx, savePath, file) // 保存文件 - err = fs.Handler.Put(ctx, file) - if err != nil { - fs.Trigger(ctx, "AfterUploadFailed", file) - return err + if file.Mode != fsctx.Nop { + err = fs.Handler.Put(ctx, file) + if err != nil { + fs.Trigger(ctx, "AfterUploadFailed", file) + return err + } } // 上传完成后的钩子 @@ -150,28 +154,26 @@ func (fs *FileSystem) CreateUploadSession(ctx context.Context, path string, size credentialTTL := model.GetIntSetting("upload_credential_timeout", 3600) callBackSessionTTL := model.GetIntSetting("upload_session_timeout", 86400) - var err error - - // 进行文件上传预检查 + callbackKey := uuid.Must(uuid.NewV4()).String() + // 创建隐藏的文件,同时校验文件信息 file := &fsctx.FileStream{ - Size: size, - Name: name, - } - - // 检查上传请求合法性 - if err := HookValidateFile(ctx, fs, file); err != nil { - return nil, err + Size: size, + Name: name, + VirtualPath: path, + Mode: fsctx.Nop, + Hidden: true, + Metadata: map[string]string{ + UploadSessionMetaKey: callbackKey, + }, } - - if err := HookValidateCapacityWithoutIncrease(ctx, fs, file); err != nil { + fs.Use("BeforeUpload", HookValidateFile) + fs.Use("AfterUpload", HookClearFileHeaderSize) + fs.Use("AfterUpload", GenericAfterUpload) + if err := fs.Upload(ctx, file); err != nil { return nil, err } - // 生成存储路径 - savePath := fs.GenerateSavePath(ctx, &fsctx.FileStream{Name: name, VirtualPath: path}) - - callbackKey := uuid.Must(uuid.NewV4()).String() uploadSession := &serializer.UploadSession{ Key: callbackKey, UID: fs.User.ID, @@ -179,7 +181,7 @@ func (fs *FileSystem) CreateUploadSession(ctx context.Context, path string, size VirtualPath: path, Name: name, Size: size, - SavePath: savePath, + SavePath: file.SavePath, ChunkSize: fs.Policy.OptionsSerialized.ChunkSize, }