fix(plugin): Add storage plugin interface

This commit is contained in:
LinkinStars 2023-03-08 16:29:55 +08:00
parent d5b5d9a51c
commit 1f05338aae
3 changed files with 77 additions and 0 deletions

View File

@ -17,9 +17,11 @@ import (
"github.com/answerdev/answer/pkg/checker"
"github.com/answerdev/answer/pkg/dir"
"github.com/answerdev/answer/pkg/uid"
"github.com/answerdev/answer/plugin"
"github.com/disintegration/imaging"
"github.com/gin-gonic/gin"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
)
const (
@ -70,6 +72,14 @@ func NewUploaderService(serviceConfig *service_config.ServiceConfig,
// UploadAvatarFile upload avatar file
func (us *UploaderService) UploadAvatarFile(ctx *gin.Context) (url string, err error) {
url, err = us.tryToUploadByPlugin(ctx, plugin.UserAvatar)
if err != nil {
return "", err
}
if len(url) > 0 {
return url, nil
}
// max size
ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, 5*1024*1024)
_, file, err := ctx.Request.FormFile("file")
@ -141,6 +151,14 @@ func (us *UploaderService) AvatarThumbFile(ctx *gin.Context, uploadPath, fileNam
func (us *UploaderService) UploadPostFile(ctx *gin.Context) (
url string, err error) {
url, err = us.tryToUploadByPlugin(ctx, plugin.UserAvatar)
if err != nil {
return "", err
}
if len(url) > 0 {
return url, nil
}
// max size
ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, 10*1024*1024)
_, file, err := ctx.Request.FormFile("file")
@ -159,6 +177,14 @@ func (us *UploaderService) UploadPostFile(ctx *gin.Context) (
func (us *UploaderService) UploadBrandingFile(ctx *gin.Context) (
url string, err error) {
url, err = us.tryToUploadByPlugin(ctx, plugin.UserAvatar)
if err != nil {
return "", err
}
if len(url) > 0 {
return url, nil
}
// max size
ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, 10*1024*1024)
_, file, err := ctx.Request.FormFile("file")
@ -200,3 +226,18 @@ func (us *UploaderService) uploadFile(ctx *gin.Context, file *multipart.FileHead
url = fmt.Sprintf("%s/uploads/%s", siteGeneral.SiteUrl, fileSubPath)
return url, nil
}
func (us *UploaderService) tryToUploadByPlugin(ctx *gin.Context, source plugin.UploadSource) (
url string, err error) {
_ = plugin.CallStorage(func(fn plugin.Storage) error {
resp := fn.UploadFile(ctx, source)
if resp.OriginalError != nil {
log.Errorf("upload file by plugin failed, err: %v", resp.OriginalError)
err = errors.BadRequest("").WithMsg(resp.DisplayErrorMsg.Translate(ctx)).WithError(err)
} else {
url = resp.FullURL
}
return nil
})
return url, err
}

View File

@ -40,6 +40,10 @@ func Register(p Base) {
if _, ok := p.(Filter); ok {
registerFilter(p.(Filter))
}
if _, ok := p.(Storage); ok {
registerStorage(p.(Storage))
}
}
type Stack[T Base] struct {

32
plugin/storage.go Normal file
View File

@ -0,0 +1,32 @@
package plugin
type UploadSource string
const (
UserAvatar UploadSource = "user_avatar"
UserPost UploadSource = "user_post"
AdminBranding UploadSource = "admin_branding"
)
type UploadFileResponse struct {
// FullURL is the URL that can be used to access the file
FullURL string
// OriginalError is the error returned by the storage plugin. It is used for debugging.
OriginalError error
// DisplayErrorMsg is the error message that will be displayed to the user.
DisplayErrorMsg Translator
}
type Storage interface {
Base
// UploadFile uploads a file to storage.
// The file is in the Form of the ctx and the key is "file"
UploadFile(ctx *GinContext, source UploadSource) UploadFileResponse
}
var (
// CallStorage is a function that calls all registered storage
CallStorage,
registerStorage = MakePlugin[Storage](false)
)