diff --git a/models/policy.go b/models/policy.go index 20f06c5..78ffae9 100644 --- a/models/policy.go +++ b/models/policy.go @@ -129,7 +129,7 @@ func (policy *Policy) GenerateFileName(uid uint, origin string) string { case "qiniu": // 七牛会将$(fname)自动替换为原始文件名 replaceTable["{originname}"] = "$(fname)" - case "local": + case "local", "remote": replaceTable["{originname}"] = origin case "oss": // OSS会将${filename}自动替换为原始文件名 diff --git a/pkg/filesystem/hooks.go b/pkg/filesystem/hooks.go index 8158f47..c0e9d53 100644 --- a/pkg/filesystem/hooks.go +++ b/pkg/filesystem/hooks.go @@ -54,7 +54,6 @@ func HookIsFileExist(ctx context.Context, fs *FileSystem) error { } // HookSlaveUploadValidate Slave模式下对文件上传的一系列验证 -// TODO 测试 func HookSlaveUploadValidate(ctx context.Context, fs *FileSystem) error { file := ctx.Value(fsctx.FileHeaderCtx).(FileHeader) policy := ctx.Value(fsctx.UploadPolicyCtx).(serializer.UploadPolicy) @@ -209,6 +208,22 @@ func GenericAfterUpdate(ctx context.Context, fs *FileSystem) error { return nil } +// SlaveAfterUpload Slave模式下上传完成钩子 +// TODO 测试 +func SlaveAfterUpload(ctx context.Context, fs *FileSystem) error { + fileHeader := ctx.Value(fsctx.FileHeaderCtx).(FileHeader) + // 构造一个model.File,用于生成缩略图 + file := model.File{ + Name: fileHeader.GetFileName(), + SourceName: ctx.Value(fsctx.SavePathCtx).(string), + } + fs.GenerateThumbnail(ctx, &file) + + // TODO 发送回调请求 + + return nil +} + // GenericAfterUpload 文件上传完成后,包含数据库操作 func GenericAfterUpload(ctx context.Context, fs *FileSystem) error { // 文件存放的虚拟路径 diff --git a/pkg/filesystem/image.go b/pkg/filesystem/image.go index 2cce0eb..81c8691 100644 --- a/pkg/filesystem/image.go +++ b/pkg/filesystem/image.go @@ -72,7 +72,11 @@ func (fs *FileSystem) GenerateThumbnail(ctx context.Context, file *model.File) { } // 更新文件的图像信息 - err = file.UpdatePicInfo(fmt.Sprintf("%d,%d", w, h)) + if file.Model.ID > 0 { + err = file.UpdatePicInfo(fmt.Sprintf("%d,%d", w, h)) + } else { + file.PicInfo = fmt.Sprintf("%d,%d", w, h) + } // 失败时删除缩略图文件 if err != nil { diff --git a/pkg/filesystem/image_test.go b/pkg/filesystem/image_test.go index 9aef93e..059647b 100644 --- a/pkg/filesystem/image_test.go +++ b/pkg/filesystem/image_test.go @@ -94,6 +94,26 @@ func TestFileSystem_GenerateThumbnail(t *testing.T) { mock.ExpectExec("UPDATE(.+)").WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectCommit() + file := &model.File{ + Model: gorm.Model{ID: 1}, + Name: "123.jpg", + SourceName: "TestFileSystem_GenerateThumbnail.jpeg", + } + + fs.GenerateThumbnail(ctx, file) + asserts.NoError(mock.ExpectationsWereMet()) + testHandler.AssertExpectations(t) + asserts.True(util.Exists("TestFileSystem_GenerateThumbnail.jpeg" + conf.ThumbConfig.FileSuffix)) + + } + + // 成功,不进行数据库更新 + { + src := CreateTestImage() + testHandler := new(FileHeaderMock) + testHandler.On("Get", testMock.Anything, "TestFileSystem_GenerateThumbnail.jpeg").Return(src, nil) + fs.Handler = testHandler + file := &model.File{ Name: "123.jpg", SourceName: "TestFileSystem_GenerateThumbnail.jpeg", @@ -119,6 +139,7 @@ func TestFileSystem_GenerateThumbnail(t *testing.T) { mock.ExpectRollback() file := &model.File{ + Model: gorm.Model{ID: 1}, Name: "123.jpg", SourceName: "TestFileSystem_GenerateThumbnail.jpeg", } @@ -132,6 +153,7 @@ func TestFileSystem_GenerateThumbnail(t *testing.T) { // 不能生成缩略图 { file := &model.File{ + Model: gorm.Model{ID: 1}, Name: "123.123", SourceName: "TestFileSystem_GenerateThumbnail.jpeg", } diff --git a/pkg/filesystem/upload.go b/pkg/filesystem/upload.go index 0cce03f..96c2c93 100644 --- a/pkg/filesystem/upload.go +++ b/pkg/filesystem/upload.go @@ -4,6 +4,7 @@ import ( "context" model "github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/pkg/filesystem/fsctx" + "github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/util" "github.com/gin-gonic/gin" "path/filepath" @@ -83,16 +84,24 @@ func (fs *FileSystem) GenerateSavePath(ctx context.Context, file FileHeader) str ) } - // 匿名文件系统使用空上传策略生成路径 - nilPolicy := model.Policy{} + // 匿名文件系统尝试根据上下文中的上传策略生成路径 + var anonymousPolicy model.Policy + if policy, ok := ctx.Value(fsctx.UploadPolicyCtx).(serializer.UploadPolicy); ok { + anonymousPolicy = model.Policy{ + Type: "remote", + AutoRename: policy.AutoRename, + DirNameRule: policy.SavePath, + FileNameRule: policy.FileName, + } + } return filepath.Join( - nilPolicy.GeneratePath( + anonymousPolicy.GeneratePath( 0, "", ), - nilPolicy.GenerateFileName( + anonymousPolicy.GenerateFileName( 0, - "", + file.GetFileName(), ), ) } diff --git a/pkg/filesystem/upload_test.go b/pkg/filesystem/upload_test.go index aa53d0c..6e103ca 100644 --- a/pkg/filesystem/upload_test.go +++ b/pkg/filesystem/upload_test.go @@ -7,6 +7,7 @@ import ( "github.com/HFO4/cloudreve/pkg/filesystem/fsctx" "github.com/HFO4/cloudreve/pkg/filesystem/local" "github.com/HFO4/cloudreve/pkg/filesystem/response" + "github.com/HFO4/cloudreve/pkg/serializer" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" @@ -139,3 +140,22 @@ func TestFileSystem_Upload(t *testing.T) { testHandller2.AssertExpectations(t) } + +func TestFileSystem_GenerateSavePath_Anonymous(t *testing.T) { + asserts := assert.New(t) + fs := FileSystem{User: &model.User{}} + ctx := context.WithValue( + context.Background(), + fsctx.UploadPolicyCtx, + serializer.UploadPolicy{ + SavePath: "{randomkey16}", + AutoRename: false, + }, + ) + + savePath := fs.GenerateSavePath(ctx, local.FileStream{ + Name: "test.test", + }) + asserts.Len(savePath, 26) + asserts.Contains(savePath, "test.test") +} diff --git a/pkg/serializer/file.go b/pkg/serializer/file.go index d20cbf2..6b3aeef 100644 --- a/pkg/serializer/file.go +++ b/pkg/serializer/file.go @@ -8,6 +8,8 @@ import ( // UploadPolicy slave模式下传递的上传策略 type UploadPolicy struct { SavePath string `json:"save_path"` + FileName string `json:"file_name"` + AutoRename bool `json:"auto_rename"` MaxSize uint64 `json:"max_size"` AllowedExtension []string `json:"allowed_extension"` CallbackURL string `json:"callback_url"` diff --git a/routers/controllers/slave.go b/routers/controllers/slave.go index d4ede24..575754e 100644 --- a/routers/controllers/slave.go +++ b/routers/controllers/slave.go @@ -24,19 +24,22 @@ func SlaveUpload(c *gin.Context) { c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)) return } + fs.Handler = local.Handler{} // 从请求中取得上传策略 uploadPolicyRaw := c.GetHeader("X-Policy") if uploadPolicyRaw == "" { c.JSON(200, serializer.ParamErr("未指定上传策略", nil)) + return } // 解析上传策略 uploadPolicy, err := serializer.DecodeUploadPolicy(uploadPolicyRaw) if err != nil { c.JSON(200, serializer.ParamErr("上传策略格式有误", err)) + return } - ctx = context.WithValue(ctx, fsctx.UploadPolicyCtx, uploadPolicy) + ctx = context.WithValue(ctx, fsctx.UploadPolicyCtx, *uploadPolicy) // 取得文件大小 fileSize, err := strconv.ParseUint(c.Request.Header.Get("Content-Length"), 10, 64) @@ -62,6 +65,7 @@ func SlaveUpload(c *gin.Context) { // 给文件系统分配钩子 fs.Use("BeforeUpload", filesystem.HookSlaveUploadValidate) fs.Use("AfterUploadCanceled", filesystem.HookDeleteTempFile) + fs.Use("AfterUpload", filesystem.SlaveAfterUpload) fs.Use("AfterValidateFailed", filesystem.HookDeleteTempFile) // 执行上传