| package handles | |
| import ( | |
| "io" | |
| "net/url" | |
| stdpath "path" | |
| "strconv" | |
| "time" | |
| "github.com/alist-org/alist/v3/pkg/tache" | |
| "github.com/alist-org/alist/v3/internal/stream" | |
| "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" | |
| ) | |
| func getLastModified(c *gin.Context) time.Time { | |
| now := time.Now() | |
| lastModifiedStr := c.GetHeader("Last-Modified") | |
| lastModifiedMillisecond, err := strconv.ParseInt(lastModifiedStr, 10, 64) | |
| if err != nil { | |
| return now | |
| } | |
| lastModified := time.UnixMilli(lastModifiedMillisecond) | |
| return lastModified | |
| } | |
| 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, err = user.JoinPath(path) | |
| if err != nil { | |
| common.ErrorResp(c, err, 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 | |
| } | |
| s := &stream.FileStream{ | |
| Obj: &model.Object{ | |
| Name: name, | |
| Size: size, | |
| Modified: getLastModified(c), | |
| }, | |
| Reader: c.Request.Body, | |
| Mimetype: c.GetHeader("Content-Type"), | |
| WebPutAsTask: asTask, | |
| } | |
| var t tache.TaskWithInfo | |
| if asTask { | |
| t, err = fs.PutAsTask(dir, s) | |
| } else { | |
| err = fs.PutDirectly(c, dir, s, true) | |
| } | |
| defer c.Request.Body.Close() | |
| if err != nil { | |
| common.ErrorResp(c, err, 500) | |
| return | |
| } | |
| if t == nil { | |
| common.SuccessResp(c) | |
| return | |
| } | |
| common.SuccessResp(c, gin.H{ | |
| "task": getTaskInfo(t), | |
| }) | |
| } | |
| 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, err = user.JoinPath(path) | |
| if err != nil { | |
| common.ErrorResp(c, err, 403) | |
| return | |
| } | |
| storage, err := fs.GetStorage(path, &fs.GetStoragesArgs{}) | |
| 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 | |
| } | |
| defer f.Close() | |
| dir, name := stdpath.Split(path) | |
| s := stream.FileStream{ | |
| Obj: &model.Object{ | |
| Name: name, | |
| Size: file.Size, | |
| Modified: getLastModified(c), | |
| }, | |
| Reader: f, | |
| Mimetype: file.Header.Get("Content-Type"), | |
| WebPutAsTask: asTask, | |
| } | |
| var t tache.TaskWithInfo | |
| if asTask { | |
| s.Reader = struct { | |
| io.Reader | |
| }{f} | |
| t, err = fs.PutAsTask(dir, &s) | |
| } else { | |
| ss, err := stream.NewSeekableStream(s, nil) | |
| if err != nil { | |
| common.ErrorResp(c, err, 500) | |
| return | |
| } | |
| err = fs.PutDirectly(c, dir, ss, true) | |
| } | |
| if err != nil { | |
| common.ErrorResp(c, err, 500) | |
| return | |
| } | |
| if t == nil { | |
| common.SuccessResp(c) | |
| return | |
| } | |
| common.SuccessResp(c, gin.H{ | |
| "task": getTaskInfo(t), | |
| }) | |
| } | |