From 4d6ab53336276f247bd12f5072412a2c40e9a12f Mon Sep 17 00:00:00 2001 From: Noah Hsu Date: Thu, 22 Sep 2022 16:53:58 +0800 Subject: [PATCH] feat: add form upload api (close #1693 #1709) --- server/handles/fsmanage.go | 56 ---------------- server/handles/fsup.go | 134 +++++++++++++++++++++++++++++++++++++ server/router.go | 3 +- 3 files changed, 136 insertions(+), 57 deletions(-) create mode 100644 server/handles/fsup.go diff --git a/server/handles/fsmanage.go b/server/handles/fsmanage.go index f9b6c298673..20f642e3095 100644 --- a/server/handles/fsmanage.go +++ b/server/handles/fsmanage.go @@ -2,10 +2,7 @@ package handles import ( "fmt" - "net/url" stdpath "path" - "strconv" - "time" "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/errs" @@ -188,59 +185,6 @@ func FsRemove(c *gin.Context) { common.SuccessResp(c) } -func FsPut(c *gin.Context) { - path := c.GetHeader("File-Path") - path, err := url.PathUnescape(path) - if err != nil { - common.ErrorResp(c, err, 400) - return - } - asTask := c.GetHeader("As-Task") == "true" - user := c.MustGet("user").(*model.User) - path = stdpath.Join(user.BasePath, path) - if !user.CanWrite() { - meta, err := db.GetNearestMeta(stdpath.Dir(path)) - if err != nil { - if !errors.Is(errors.Cause(err), errs.MetaNotFound) { - common.ErrorResp(c, err, 500, true) - return - } - } - if !canWrite(meta, path) { - common.ErrorResp(c, errs.PermissionDenied, 403) - return - } - } - - dir, name := stdpath.Split(path) - sizeStr := c.GetHeader("Content-Length") - size, err := strconv.ParseInt(sizeStr, 10, 64) - if err != nil { - common.ErrorResp(c, err, 400) - return - } - stream := &model.FileStream{ - Obj: &model.Object{ - Name: name, - Size: size, - Modified: time.Now(), - }, - ReadCloser: c.Request.Body, - Mimetype: c.GetHeader("Content-Type"), - WebPutAsTask: asTask, - } - if asTask { - err = fs.PutAsTask(dir, stream) - } else { - err = fs.PutDirectly(c, dir, stream) - } - if err != nil { - common.ErrorResp(c, err, 500) - return - } - common.SuccessResp(c) -} - // Link return real link, just for proxy program, it may contain cookie, so just allowed for admin func Link(c *gin.Context) { var req MkdirOrLinkReq diff --git a/server/handles/fsup.go b/server/handles/fsup.go new file mode 100644 index 00000000000..185cec1cab7 --- /dev/null +++ b/server/handles/fsup.go @@ -0,0 +1,134 @@ +package handles + +import ( + "net/url" + stdpath "path" + "strconv" + "time" + + "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/errs" + "github.com/alist-org/alist/v3/internal/fs" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/server/common" + "github.com/gin-gonic/gin" + "github.com/pkg/errors" +) + +func FsStream(c *gin.Context) { + path := c.GetHeader("File-Path") + path, err := url.PathUnescape(path) + if err != nil { + common.ErrorResp(c, err, 400) + return + } + asTask := c.GetHeader("As-Task") == "true" + user := c.MustGet("user").(*model.User) + path = stdpath.Join(user.BasePath, path) + if !user.CanWrite() { + meta, err := db.GetNearestMeta(stdpath.Dir(path)) + if err != nil { + if !errors.Is(errors.Cause(err), errs.MetaNotFound) { + common.ErrorResp(c, err, 500, true) + return + } + } + if !canWrite(meta, path) { + common.ErrorResp(c, errs.PermissionDenied, 403) + return + } + } + + dir, name := stdpath.Split(path) + sizeStr := c.GetHeader("Content-Length") + size, err := strconv.ParseInt(sizeStr, 10, 64) + if err != nil { + common.ErrorResp(c, err, 400) + return + } + stream := &model.FileStream{ + Obj: &model.Object{ + Name: name, + Size: size, + Modified: time.Now(), + }, + ReadCloser: c.Request.Body, + Mimetype: c.GetHeader("Content-Type"), + WebPutAsTask: asTask, + } + if asTask { + err = fs.PutAsTask(dir, stream) + } else { + err = fs.PutDirectly(c, dir, stream) + } + if err != nil { + common.ErrorResp(c, err, 500) + return + } + common.SuccessResp(c) +} + +func FsForm(c *gin.Context) { + path := c.GetHeader("File-Path") + path, err := url.PathUnescape(path) + if err != nil { + common.ErrorResp(c, err, 400) + return + } + asTask := c.GetHeader("As-Task") == "true" + user := c.MustGet("user").(*model.User) + path = stdpath.Join(user.BasePath, path) + if !user.CanWrite() { + meta, err := db.GetNearestMeta(stdpath.Dir(path)) + if err != nil { + if !errors.Is(errors.Cause(err), errs.MetaNotFound) { + common.ErrorResp(c, err, 500, true) + return + } + } + if !canWrite(meta, path) { + common.ErrorResp(c, errs.PermissionDenied, 403) + return + } + } + storage, err := fs.GetStorage(path) + if err != nil { + common.ErrorResp(c, err, 400) + return + } + if storage.Config().NoUpload { + common.ErrorStrResp(c, "Current storage doesn't support upload", 405) + return + } + file, err := c.FormFile("file") + if err != nil { + common.ErrorResp(c, err, 500) + return + } + f, err := file.Open() + if err != nil { + common.ErrorResp(c, err, 500) + return + } + dir, name := stdpath.Split(path) + stream := &model.FileStream{ + Obj: &model.Object{ + Name: name, + Size: file.Size, + Modified: time.Now(), + }, + ReadCloser: f, + Mimetype: file.Header.Get("Content-Type"), + WebPutAsTask: false, + } + if asTask { + err = fs.PutAsTask(dir, stream) + } else { + err = fs.PutDirectly(c, dir, stream) + } + if err != nil { + common.ErrorResp(c, err, 500) + return + } + common.SuccessResp(c) +} diff --git a/server/router.go b/server/router.go index 18b5211910b..098ffebae18 100644 --- a/server/router.go +++ b/server/router.go @@ -119,7 +119,8 @@ func _fs(g *gin.RouterGroup) { g.POST("/move", handles.FsMove) g.POST("/copy", handles.FsCopy) g.POST("/remove", handles.FsRemove) - g.PUT("/put", handles.FsPut) + g.PUT("/put", handles.FsStream) + g.PUT("/form", handles.FsForm) g.POST("/link", middlewares.AuthAdmin, handles.Link) g.POST("/add_aria2", handles.AddAria2) }