mirror of
https://github.com/AlistGo/alist.git
synced 2025-06-21 12:51:58 +08:00
🚧 webdav write interface
This commit is contained in:
@ -15,6 +15,7 @@ import (
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -133,6 +134,45 @@ func (fs *FileSystem) CreateDirectory(ctx context.Context, reqPath string) (inte
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (fs *FileSystem) Upload(ctx context.Context, r *http.Request, rawPath string) error {
|
||||
rawPath = utils.ParsePath(rawPath)
|
||||
if model.AccountsCount() > 1 && rawPath == "/" {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
account, path_, driver, err := ParsePath(rawPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileSize, err := strconv.ParseUint(r.Header.Get("Content-Length"), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filePath, fileName := filepath.Split(path_)
|
||||
fileData := model.FileStream{
|
||||
MIMEType: r.Header.Get("Content-Type"),
|
||||
File: r.Body,
|
||||
Size: fileSize,
|
||||
Name: fileName,
|
||||
Path: filePath,
|
||||
}
|
||||
return driver.Upload(&fileData, account)
|
||||
}
|
||||
|
||||
func (fs *FileSystem) Delete(rawPath string) error {
|
||||
rawPath = utils.ParsePath(rawPath)
|
||||
if rawPath == "/" {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
if model.AccountsCount() > 1 && len(strings.Split(rawPath, "/")) < 2 {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
account, path_, driver, err := ParsePath(rawPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return driver.Delete(path_, account)
|
||||
}
|
||||
|
||||
// slashClean is equivalent to but slightly more efficient than
|
||||
// path.Clean("/" + name).
|
||||
func slashClean(name string) string {
|
||||
@ -145,16 +185,55 @@ func slashClean(name string) string {
|
||||
// moveFiles moves files and/or directories from src to dst.
|
||||
//
|
||||
// See section 9.9.4 for when various HTTP status codes apply.
|
||||
func moveFiles(ctx context.Context, fs *FileSystem, src FileInfo, dst string, overwrite bool) (status int, err error) {
|
||||
|
||||
func moveFiles(ctx context.Context, fs *FileSystem, src string, dst string, overwrite bool) (status int, err error) {
|
||||
src = utils.ParsePath(src)
|
||||
dst = utils.ParsePath(dst)
|
||||
if src == dst {
|
||||
return http.StatusMethodNotAllowed, errDestinationEqualsSource
|
||||
}
|
||||
srcAccount, srcPath, driver, err := ParsePath(src)
|
||||
if err != nil {
|
||||
return http.StatusMethodNotAllowed, err
|
||||
}
|
||||
dstAccount, dstPath, _, err := ParsePath(dst)
|
||||
if err != nil {
|
||||
return http.StatusMethodNotAllowed, err
|
||||
}
|
||||
if srcAccount.Name != dstAccount.Name {
|
||||
return http.StatusMethodNotAllowed, errInvalidDestination
|
||||
}
|
||||
err = driver.Move(srcPath,dstPath,srcAccount)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
return http.StatusNoContent, nil
|
||||
}
|
||||
|
||||
// copyFiles copies files and/or directories from src to dst.
|
||||
//
|
||||
// See section 9.8.5 for when various HTTP status codes apply.
|
||||
func copyFiles(ctx context.Context, fs *FileSystem, src FileInfo, dst string, overwrite bool, depth int, recursion int) (status int, err error) {
|
||||
|
||||
func copyFiles(ctx context.Context, fs *FileSystem, src string, dst string, overwrite bool, depth int, recursion int) (status int, err error) {
|
||||
src = utils.ParsePath(src)
|
||||
dst = utils.ParsePath(dst)
|
||||
if src == dst {
|
||||
return http.StatusMethodNotAllowed, errDestinationEqualsSource
|
||||
}
|
||||
srcAccount, srcPath, driver, err := ParsePath(src)
|
||||
if err != nil {
|
||||
return http.StatusMethodNotAllowed, err
|
||||
}
|
||||
dstAccount, dstPath, _, err := ParsePath(dst)
|
||||
if err != nil {
|
||||
return http.StatusMethodNotAllowed, err
|
||||
}
|
||||
if srcAccount.Name != dstAccount.Name {
|
||||
// TODO 跨账号复制
|
||||
return http.StatusMethodNotAllowed, errInvalidDestination
|
||||
}
|
||||
err = driver.Copy(srcPath,dstPath,srcAccount)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
return http.StatusNoContent, nil
|
||||
}
|
||||
|
||||
|
@ -253,26 +253,11 @@ func (h *Handler) handleDelete(w http.ResponseWriter, r *http.Request, fs *FileS
|
||||
return status, err
|
||||
}
|
||||
defer release()
|
||||
|
||||
//ctx := r.Context()
|
||||
|
||||
//// 尝试作为文件删除
|
||||
//if ok, file := fs.IsFileExist(reqPath); ok {
|
||||
// if err := fs.Delete(ctx, []uint{}, []uint{file.ID}, false); err != nil {
|
||||
// return http.StatusMethodNotAllowed, err
|
||||
// }
|
||||
// return http.StatusNoContent, nil
|
||||
//}
|
||||
//
|
||||
//// 尝试作为目录删除
|
||||
//if ok, folder := fs.IsPathExist(reqPath); ok {
|
||||
// if err := fs.Delete(ctx, []uint{folder.ID}, []uint{}, false); err != nil {
|
||||
// return http.StatusMethodNotAllowed, err
|
||||
// }
|
||||
// return http.StatusNoContent, nil
|
||||
//}
|
||||
|
||||
return http.StatusNotFound, nil
|
||||
err = fs.Delete(reqPath)
|
||||
if err != nil {
|
||||
return http.StatusMethodNotAllowed, err
|
||||
}
|
||||
return http.StatusNoContent, nil
|
||||
}
|
||||
|
||||
// OK
|
||||
@ -291,6 +276,11 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request, fs *FileSyst
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
err = fs.Upload(ctx, r, reqPath)
|
||||
if err != nil {
|
||||
return http.StatusMethodNotAllowed, err
|
||||
}
|
||||
|
||||
etag, err := findETag(ctx, fs, h.LockSystem, reqPath, nil)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
@ -361,7 +351,7 @@ func (h *Handler) handleCopyMove(w http.ResponseWriter, r *http.Request, fs *Fil
|
||||
|
||||
ctx := r.Context()
|
||||
|
||||
isExist, target := isPathExist(ctx, fs, src)
|
||||
isExist, _ := isPathExist(ctx, fs, src)
|
||||
|
||||
if !isExist {
|
||||
return http.StatusNotFound, nil
|
||||
@ -390,7 +380,7 @@ func (h *Handler) handleCopyMove(w http.ResponseWriter, r *http.Request, fs *Fil
|
||||
return http.StatusBadRequest, errInvalidDepth
|
||||
}
|
||||
}
|
||||
return copyFiles(ctx, fs, target, dst, r.Header.Get("Overwrite") != "F", depth, 0)
|
||||
return copyFiles(ctx, fs, src, dst, r.Header.Get("Overwrite") != "F", depth, 0)
|
||||
}
|
||||
|
||||
// windows下,某些情况下(网盘根目录下)Office保存文件时附带的锁token只包含源文件,
|
||||
@ -409,7 +399,7 @@ func (h *Handler) handleCopyMove(w http.ResponseWriter, r *http.Request, fs *Fil
|
||||
return http.StatusBadRequest, errInvalidDepth
|
||||
}
|
||||
}
|
||||
return moveFiles(ctx, fs, target, dst, r.Header.Get("Overwrite") == "T")
|
||||
return moveFiles(ctx, fs, src, dst, r.Header.Get("Overwrite") == "T")
|
||||
}
|
||||
|
||||
// OK
|
||||
|
Reference in New Issue
Block a user