mirror of
https://github.com/halejohn/Cloudreve.git
synced 2026-01-27 18:11:57 +08:00
feat(webdav): supoort rename in copy and move (#1774)
This commit is contained in:
@@ -35,4 +35,6 @@ const (
|
||||
CancelFuncCtx
|
||||
// 文件在从机节点中的路径
|
||||
SlaveSrcPath
|
||||
// Webdav目标名称
|
||||
WebdavDstName
|
||||
)
|
||||
|
||||
@@ -69,6 +69,11 @@ func (fs *FileSystem) Copy(ctx context.Context, dirs, files []uint, src, dst str
|
||||
// 记录复制的文件的总容量
|
||||
var newUsedStorage uint64
|
||||
|
||||
// 设置webdav目标名
|
||||
if dstName, ok := ctx.Value(fsctx.WebdavDstName).(string); ok {
|
||||
dstFolder.WebdavDstName = dstName
|
||||
}
|
||||
|
||||
// 复制目录
|
||||
if len(dirs) > 0 {
|
||||
subFileSizes, err := srcFolder.CopyFolderTo(dirs[0], dstFolder)
|
||||
@@ -103,6 +108,11 @@ func (fs *FileSystem) Move(ctx context.Context, dirs, files []uint, src, dst str
|
||||
return ErrPathNotExist
|
||||
}
|
||||
|
||||
// 设置webdav目标名
|
||||
if dstName, ok := ctx.Value(fsctx.WebdavDstName).(string); ok {
|
||||
dstFolder.WebdavDstName = dstName
|
||||
}
|
||||
|
||||
// 处理目录及子文件移动
|
||||
err := srcFolder.MoveFolderTo(dirs, dstFolder)
|
||||
if err != nil {
|
||||
|
||||
@@ -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