mirror of
https://github.com/halejohn/Cloudreve.git
synced 2026-01-26 09:34:57 +08:00
feat(webdav): supoort rename in copy and move (#1774)
This commit is contained in:
@@ -9,9 +9,12 @@ import (
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
|
||||
)
|
||||
|
||||
// slashClean is equivalent to but slightly more efficient than
|
||||
@@ -23,6 +26,31 @@ func slashClean(name string) string {
|
||||
return path.Clean(name)
|
||||
}
|
||||
|
||||
// 更新Copy或Move后的修改时间
|
||||
func updateCopyMoveModtime(req *http.Request, fs *filesystem.FileSystem, dst string) error {
|
||||
var modtime time.Time
|
||||
if timeVal := req.Header.Get("X-OC-Mtime"); timeVal != "" {
|
||||
timeUnix, err := strconv.ParseInt(timeVal, 10, 64)
|
||||
if err == nil {
|
||||
modtime = time.Unix(timeUnix, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if modtime.IsZero() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ok, fi := isPathExist(req.Context(), fs, dst)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
return model.DB.Model(fi.(*model.Folder)).UpdateColumn("updated_at", modtime).Error
|
||||
}
|
||||
return model.DB.Model(fi.(*model.File)).UpdateColumn("updated_at", modtime).Error
|
||||
}
|
||||
|
||||
// moveFiles moves files and/or directories from src to dst.
|
||||
//
|
||||
// See section 9.9.4 for when various HTTP status codes apply.
|
||||
@@ -44,20 +72,17 @@ func moveFiles(ctx context.Context, fs *filesystem.FileSystem, src FileInfo, dst
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 判断是否需要移动
|
||||
if src.GetPosition() != path.Dir(dst) {
|
||||
err = fs.Move(
|
||||
ctx,
|
||||
context.WithValue(ctx, fsctx.WebdavDstName, path.Base(dst)),
|
||||
folderIDs,
|
||||
fileIDs,
|
||||
src.GetPosition(),
|
||||
path.Dir(dst),
|
||||
)
|
||||
}
|
||||
|
||||
// 判断是否需要重命名
|
||||
if err == nil && src.GetName() != path.Base(dst) {
|
||||
} else if src.GetName() != path.Base(dst) {
|
||||
// 判断是否需要重命名
|
||||
err = fs.Rename(
|
||||
ctx,
|
||||
folderIDs,
|
||||
@@ -81,7 +106,6 @@ func copyFiles(ctx context.Context, fs *filesystem.FileSystem, src FileInfo, dst
|
||||
}
|
||||
recursion++
|
||||
|
||||
|
||||
var (
|
||||
fileIDs []uint
|
||||
folderIDs []uint
|
||||
@@ -100,7 +124,7 @@ func copyFiles(ctx context.Context, fs *filesystem.FileSystem, src FileInfo, dst
|
||||
}
|
||||
|
||||
err = fs.Copy(
|
||||
ctx,
|
||||
context.WithValue(ctx, fsctx.WebdavDstName, path.Base(dst)),
|
||||
folderIDs,
|
||||
fileIDs,
|
||||
src.GetPosition(),
|
||||
|
||||
@@ -496,7 +496,16 @@ 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)
|
||||
status, err = copyFiles(ctx, fs, target, dst, r.Header.Get("Overwrite") != "F", depth, 0)
|
||||
if err != nil {
|
||||
return status, err
|
||||
}
|
||||
|
||||
err = updateCopyMoveModtime(r, fs, dst)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// windows下,某些情况下(网盘根目录下)Office保存文件时附带的锁token只包含源文件,
|
||||
@@ -515,7 +524,16 @@ 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")
|
||||
status, err = moveFiles(ctx, fs, target, dst, r.Header.Get("Overwrite") == "T")
|
||||
if err != nil {
|
||||
return status, err
|
||||
}
|
||||
|
||||
err = updateCopyMoveModtime(r, fs, dst)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// OK
|
||||
|
||||
Reference in New Issue
Block a user