From 352a6a741a997f0a61f5430224ca10c837b38c6a Mon Sep 17 00:00:00 2001 From: Andy Hsu Date: Wed, 13 Sep 2023 15:45:57 +0800 Subject: [PATCH] feat(webdav): support copy directly without task (close #5206) --- internal/conf/const.go | 7 ++++++- internal/fs/copy.go | 26 ++++++++++++++++++++++++++ server/webdav/file.go | 4 +++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/internal/conf/const.go b/internal/conf/const.go index b131c661525..1cda3e322dc 100644 --- a/internal/conf/const.go +++ b/internal/conf/const.go @@ -41,7 +41,7 @@ const ( OcrApi = "ocr_api" FilenameCharMapping = "filename_char_mapping" ForwardDirectLinkParams = "forward_direct_link_params" - WebauthnLoginEnabled = "webauthn_login_enabled" + WebauthnLoginEnabled = "webauthn_login_enabled" // index SearchIndex = "search_index" @@ -84,3 +84,8 @@ const ( TEXT IMAGE ) + +// ContextKey is the type of context keys. +const ( + NoTaskKey = "no_task" +) diff --git a/internal/fs/copy.go b/internal/fs/copy.go index caf858826ae..c3e387cb227 100644 --- a/internal/fs/copy.go +++ b/internal/fs/copy.go @@ -7,6 +7,7 @@ import ( stdpath "path" "sync/atomic" + "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/op" @@ -36,6 +37,31 @@ func _copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool if srcStorage.GetStorage() == dstStorage.GetStorage() { return false, op.Copy(ctx, srcStorage, srcObjActualPath, dstDirActualPath, lazyCache...) } + if ctx.Value(conf.NoTaskKey) != nil { + srcObj, err := op.Get(ctx, srcStorage, srcObjActualPath) + if err != nil { + return false, errors.WithMessagef(err, "failed get src [%s] file", srcObjPath) + } + if !srcObj.IsDir() { + // copy file directly + link, _, err := op.Link(ctx, srcStorage, srcObjActualPath, model.LinkArgs{ + Header: http.Header{}, + }) + if err != nil { + return false, errors.WithMessagef(err, "failed get [%s] link", srcObjPath) + } + fs := stream.FileStream{ + Obj: srcObj, + Ctx: ctx, + } + // any link provided is seekable + ss, err := stream.NewSeekableStream(fs, link) + if err != nil { + return false, errors.WithMessagef(err, "failed get [%s] stream", srcObjPath) + } + return false, op.Put(ctx, dstStorage, dstDirActualPath, ss, nil, false) + } + } // not in the same storage CopyTaskManager.Submit(task.WithCancelCtx(&task.Task[uint64]{ Name: fmt.Sprintf("copy [%s](%s) to [%s](%s)", srcStorage.GetStorage().MountPath, srcObjActualPath, dstStorage.GetStorage().MountPath, dstDirActualPath), diff --git a/server/webdav/file.go b/server/webdav/file.go index 2832336f423..01e96f7d223 100644 --- a/server/webdav/file.go +++ b/server/webdav/file.go @@ -10,6 +10,7 @@ import ( "path" "path/filepath" + "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/op" @@ -54,7 +55,8 @@ func moveFiles(ctx context.Context, src, dst string, overwrite bool) (status int // // See section 9.8.5 for when various HTTP status codes apply. func copyFiles(ctx context.Context, src, dst string, overwrite bool) (status int, err error) { - _, err = fs.Copy(ctx, src, dst) + dstDir := path.Dir(dst) + _, err = fs.Copy(context.WithValue(ctx, conf.NoTaskKey, struct{}{}), src, dstDir) if err != nil { return http.StatusInternalServerError, err }