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})
}
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 {

@ -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("物理同名文件已存在或不可用")

@ -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"
}

@ -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 != "" {

@ -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"
}

@ -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")

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

@ -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)
}

@ -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
}

@ -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

@ -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,
}

Loading…
Cancel
Save