Feat: create hidden file when creating upload session

pull/1107/head
HFO4 2 years ago
parent 868a88e5fc
commit e37e93a7b6

@ -352,7 +352,7 @@ func (handler Driver) Token(ctx context.Context, ttl int64, uploadSession *seria
[]interface{}{"content-length-range", 0, handler.Policy.MaxSize}) []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 { if err == nil {
res.Callback = apiURL res.Callback = apiURL
res.Key = uploadSession.Key res.Key = uploadSession.Key
@ -375,13 +375,7 @@ func (handler Driver) Meta(ctx context.Context, path string) (*MetaData, error)
}, nil }, nil
} }
func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, keyTime string) (serializer.UploadCredential, error) { func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, keyTime string, savePath string) (serializer.UploadCredential, error) {
// 读取上下文中生成的存储路径
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
if !ok {
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
}
// 编码上传策略 // 编码上传策略
policyJSON, err := json.Marshal(policy) policyJSON, err := json.Marshal(policy)
if err != nil { if err != nil {

@ -88,7 +88,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
dst := util.RelativePath(filepath.FromSlash(file.GetSavePath())) dst := util.RelativePath(filepath.FromSlash(file.GetSavePath()))
// 如果非 Overwrite则检查是否有重名冲突 // 如果非 Overwrite则检查是否有重名冲突
if file.GetMode() != fsctx.Overwrite { if file.GetMode() == fsctx.Create {
if util.Exists(dst) { if util.Exists(dst) {
util.Log().Warning("物理同名文件已存在或不可用: %s", dst) util.Log().Warning("物理同名文件已存在或不可用: %s", dst)
return errors.New("物理同名文件已存在或不可用") return errors.New("物理同名文件已存在或不可用")

@ -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 { func (client *Client) Upload(ctx context.Context, file fsctx.FileHeader) error {
// 决定是否覆盖文件 // 决定是否覆盖文件
overwrite := "replace" overwrite := "replace"
if file.GetMode() != fsctx.Overwrite { if file.GetMode() != fsctx.Create {
overwrite = "fail" overwrite = "fail"
} }

@ -237,7 +237,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
// 是否允许覆盖 // 是否允许覆盖
overwrite := true overwrite := true
if file.GetMode() != fsctx.Overwrite { if file.GetMode() == fsctx.Create {
overwrite = false 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}) []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) { func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, callback CallbackPolicy, TTL int64, savePath string) (serializer.UploadCredential, error) {
// 读取上下文中生成的存储路径
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
if !ok {
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
}
// 处理回调策略 // 处理回调策略
callbackPolicyEncoded := "" callbackPolicyEncoded := ""
if callback.CallbackURL != "" { if callback.CallbackURL != "" {

@ -156,7 +156,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
// 决定是否要禁用文件覆盖 // 决定是否要禁用文件覆盖
overwrite := "true" overwrite := "true"
if file.GetMode() != fsctx.Overwrite { if file.GetMode() != fsctx.Create {
overwrite = "false" overwrite = "false"
} }

@ -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 获取文件信息 // 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) { func (handler Driver) getUploadCredential(ctx context.Context, policy UploadPolicy, callback *url.URL, savePath string) (serializer.UploadCredential, error) {
// 读取上下文中生成的存储路径和文件大小
savePath, ok := ctx.Value(fsctx.SavePathCtx).(string)
if !ok {
return serializer.UploadCredential{}, errors.New("无法获取存储路径")
}
longDate := time.Now().UTC().Format("20060102T150405Z") longDate := time.Now().UTC().Format("20060102T150405Z")
shortDate := time.Now().UTC().Format("20060102") shortDate := time.Now().UTC().Format("20060102")

@ -5,10 +5,6 @@ type key int
const ( const (
// GinCtx Gin的上下文 // GinCtx Gin的上下文
GinCtx key = iota GinCtx key = iota
// SavePathCtx 文件物理路径
SavePathCtx
// FileHeaderCtx 上传的文件
FileHeaderCtx
// PathCtx 文件或目录的虚拟路径 // PathCtx 文件或目录的虚拟路径
PathCtx PathCtx
// FileModelCtx 文件数据库模型 // FileModelCtx 文件数据库模型

@ -9,8 +9,10 @@ type WriteMode int
const ( const (
Overwrite WriteMode = iota Overwrite WriteMode = iota
// Append 只适用于本地策略
Append Append
Create Create
Nop
) )
// FileStream 用户传来的文件 // FileStream 用户传来的文件
@ -71,6 +73,10 @@ func (file *FileStream) GetSavePath() string {
return file.SavePath return file.SavePath
} }
func (file *FileStream) SetSize(size uint64) {
file.Size = size
}
// FileHeader 上传来的文件数据处理器 // FileHeader 上传来的文件数据处理器
type FileHeader interface { type FileHeader interface {
io.Reader io.Reader
@ -84,4 +90,5 @@ type FileHeader interface {
GetLastModified() time.Time GetLastModified() time.Time
IsHidden() bool IsHidden() bool
GetSavePath() string GetSavePath() string
SetSize(uint64)
} }

@ -284,7 +284,7 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem, fileHeader fsctx.Fi
// 检查文件是否存在 // 检查文件是否存在
if ok, _ := fs.IsChildFileExist( if ok, _ := fs.IsChildFileExist(
folder, folder,
ctx.Value(fsctx.FileHeaderCtx).(fsctx.FileHeader).GetFileName(), fileHeader.GetFileName(),
); ok { ); ok {
return ErrFileExisted return ErrFileExisted
} }
@ -307,3 +307,9 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem, fileHeader fsctx.Fi
return nil return nil
} }
// HookClearFileHeaderSize 将FileHeader大小设定为0
func HookClearFileHeaderSize(ctx context.Context, fs *FileSystem, fileHeader fsctx.FileHeader) error {
fileHeader.SetSize(0)
return nil
}

@ -350,20 +350,22 @@ func (fs *FileSystem) listObjects(ctx context.Context, parent string, files []mo
} }
} }
newFile := serializer.Object{ if !file.Hidden {
ID: hashid.HashID(file.ID, hashid.FileID), newFile := serializer.Object{
Name: file.Name, ID: hashid.HashID(file.ID, hashid.FileID),
Path: processedPath, Name: file.Name,
Pic: file.PicInfo, Path: processedPath,
Size: file.Size, Pic: file.PicInfo,
Type: "file", Size: file.Size,
Date: file.CreatedAt, Type: "file",
SourceEnabled: file.GetPolicy().IsOriginLinkEnable, Date: file.CreatedAt,
} SourceEnabled: file.GetPolicy().IsOriginLinkEnable,
if shareKey != "" { }
newFile.Key = shareKey if shareKey != "" {
newFile.Key = shareKey
}
objects = append(objects, newFile)
} }
objects = append(objects, newFile)
} }
return objects return objects

@ -20,10 +20,12 @@ import (
================ ================
*/ */
const (
UploadSessionMetaKey = "upload_session"
)
// Upload 上传文件 // Upload 上传文件
func (fs *FileSystem) Upload(ctx context.Context, file *fsctx.FileStream) (err error) { 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) err = fs.Trigger(ctx, "BeforeUpload", file)
if err != nil { 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) go fs.CancelUpload(ctx, savePath, file)
// 保存文件 // 保存文件
err = fs.Handler.Put(ctx, file) if file.Mode != fsctx.Nop {
if err != nil { err = fs.Handler.Put(ctx, file)
fs.Trigger(ctx, "AfterUploadFailed", file) if err != nil {
return err 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) credentialTTL := model.GetIntSetting("upload_credential_timeout", 3600)
callBackSessionTTL := model.GetIntSetting("upload_session_timeout", 86400) callBackSessionTTL := model.GetIntSetting("upload_session_timeout", 86400)
var err error callbackKey := uuid.Must(uuid.NewV4()).String()
// 进行文件上传预检查
// 创建隐藏的文件,同时校验文件信息
file := &fsctx.FileStream{ file := &fsctx.FileStream{
Size: size, Size: size,
Name: name, Name: name,
} VirtualPath: path,
Mode: fsctx.Nop,
// 检查上传请求合法性 Hidden: true,
if err := HookValidateFile(ctx, fs, file); err != nil { Metadata: map[string]string{
return nil, err UploadSessionMetaKey: callbackKey,
},
} }
fs.Use("BeforeUpload", HookValidateFile)
if err := HookValidateCapacityWithoutIncrease(ctx, fs, file); err != nil { fs.Use("AfterUpload", HookClearFileHeaderSize)
fs.Use("AfterUpload", GenericAfterUpload)
if err := fs.Upload(ctx, file); err != nil {
return nil, err return nil, err
} }
// 生成存储路径
savePath := fs.GenerateSavePath(ctx, &fsctx.FileStream{Name: name, VirtualPath: path})
callbackKey := uuid.Must(uuid.NewV4()).String()
uploadSession := &serializer.UploadSession{ uploadSession := &serializer.UploadSession{
Key: callbackKey, Key: callbackKey,
UID: fs.User.ID, UID: fs.User.ID,
@ -179,7 +181,7 @@ func (fs *FileSystem) CreateUploadSession(ctx context.Context, path string, size
VirtualPath: path, VirtualPath: path,
Name: name, Name: name,
Size: size, Size: size,
SavePath: savePath, SavePath: file.SavePath,
ChunkSize: fs.Policy.OptionsSerialized.ChunkSize, ChunkSize: fs.Policy.OptionsSerialized.ChunkSize,
} }

Loading…
Cancel
Save