diff --git a/drivers/115_open/driver.go b/drivers/115_open/driver.go index edab65abe..fe6d33d66 100644 --- a/drivers/115_open/driver.go +++ b/drivers/115_open/driver.go @@ -131,7 +131,7 @@ func (d *Open115) Link(ctx context.Context, file model.Obj, args model.LinkArgs) }, nil } -func (d *Open115) GetObjInfo(ctx context.Context, path string) (model.Obj, error) { +func (d *Open115) Get(ctx context.Context, path string) (model.Obj, error) { if err := d.WaitLimit(ctx); err != nil { return nil, err } diff --git a/drivers/alias/driver.go b/drivers/alias/driver.go index bf83640d3..957de1dca 100644 --- a/drivers/alias/driver.go +++ b/drivers/alias/driver.go @@ -73,14 +73,15 @@ func (d *Alias) Drop(ctx context.Context) error { return nil } +func (d *Alias) GetRoot(ctx context.Context) (model.Obj, error) { + return &model.Object{ + Name: "Root", + IsFolder: true, + Path: "/", + }, nil +} + func (d *Alias) Get(ctx context.Context, path string) (model.Obj, error) { - if utils.PathEqual(path, "/") { - return &model.Object{ - Name: "Root", - IsFolder: true, - Path: "/", - }, nil - } root, sub := d.getRootAndPath(path) dsts, ok := d.pathMap[root] if !ok { diff --git a/drivers/aliyundrive_open/driver.go b/drivers/aliyundrive_open/driver.go index 20dd92dca..caafba1a2 100644 --- a/drivers/aliyundrive_open/driver.go +++ b/drivers/aliyundrive_open/driver.go @@ -4,7 +4,9 @@ import ( "context" "errors" "net/http" + stdpath "path" "path/filepath" + "slices" "time" "github.com/OpenListTeam/OpenList/v4/drivers/base" @@ -52,6 +54,34 @@ func (d *AliyundriveOpen) Init(ctx context.Context) error { userid := utils.Json.Get(res, "user_id").ToString() d.limiter.free() d.limiter = getLimiterForUser(userid) // Allocate a corresponding limiter for each user. + + d.buildRootPath(ctx) + return nil +} + +func (d *AliyundriveOpen) buildRootPath(ctx context.Context) error { + d.RootPath = "/" + if d.RootFolderID == "root" { + return nil + } + currentFileId := d.RootFolderID + var pathSegments []string + for currentFileId != "root" { + var resp File + _, err := d.request(ctx, limiterOther, "/adrive/v1.0/openFile/get", http.MethodPost, func(req *resty.Request) { + req.SetBody(base.Json{ + "drive_id": d.DriveId, + "file_id": currentFileId, + }).SetResult(&resp) + }) + if err != nil { + return err + } + pathSegments = append(pathSegments, resp.Name) + currentFileId = resp.ParentFileId + } + slices.Reverse(pathSegments) + d.RootPath = stdpath.Join(d.RootPath, stdpath.Join(pathSegments...)) return nil } @@ -83,6 +113,25 @@ func (d *AliyundriveOpen) GetRoot(ctx context.Context) (model.Obj, error) { }, nil } +func (d *AliyundriveOpen) Get(ctx context.Context, path string) (model.Obj, error) { + if d.RootPath != "/" { + path = stdpath.Join(d.RootPath, path) + } + var resp File + _, err := d.request(ctx, limiterOther, "/adrive/v1.0/openFile/get_by_path", http.MethodPost, func(req *resty.Request) { + req.SetBody(base.Json{ + "drive_id": d.DriveId, + "file_path": path, + }).SetResult(&resp) + }) + if err != nil { + return nil, err + } + obj := fileToObj(resp) + obj.Path = path + return obj, nil +} + func (d *AliyundriveOpen) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { files, err := d.getFiles(ctx, dir.GetID()) if err != nil { diff --git a/drivers/aliyundrive_open/meta.go b/drivers/aliyundrive_open/meta.go index d76fc2eaa..e393dbdd6 100644 --- a/drivers/aliyundrive_open/meta.go +++ b/drivers/aliyundrive_open/meta.go @@ -21,6 +21,7 @@ type Addition struct { InternalUpload bool `json:"internal_upload" help:"If you are using Aliyun ECS is located in Beijing, you can turn it on to boost the upload speed"` LIVPDownloadFormat string `json:"livp_download_format" type:"select" options:"jpeg,mov" default:"jpeg"` AccessToken string + RootPath string } var config = driver.Config{ diff --git a/drivers/chunk/driver.go b/drivers/chunk/driver.go index 572f9936b..e03503f9c 100644 --- a/drivers/chunk/driver.go +++ b/drivers/chunk/driver.go @@ -52,14 +52,15 @@ func (d *Chunk) Drop(ctx context.Context) error { return nil } +func (d *Chunk) GetRoot(ctx context.Context) (model.Obj, error) { + return &model.Object{ + Name: "Root", + IsFolder: true, + Path: "/", + }, nil +} + func (d *Chunk) Get(ctx context.Context, path string) (model.Obj, error) { - if utils.PathEqual(path, "/") { - return &model.Object{ - Name: "Root", - IsFolder: true, - Path: "/", - }, nil - } remoteStorage, remoteActualPath, err := op.GetStorageAndActualPath(d.RemotePath) if err != nil { return nil, err diff --git a/drivers/crypt/driver.go b/drivers/crypt/driver.go index b00a2ea05..3d44a2e20 100644 --- a/drivers/crypt/driver.go +++ b/drivers/crypt/driver.go @@ -186,14 +186,15 @@ func (d *Crypt) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([ return result, nil } +func (d *Crypt) GetRoot(ctx context.Context) (model.Obj, error) { + return &model.Object{ + Name: "Root", + IsFolder: true, + Path: "/", + }, nil +} + func (d *Crypt) Get(ctx context.Context, path string) (model.Obj, error) { - if utils.PathEqual(path, "/") { - return &model.Object{ - Name: "Root", - IsFolder: true, - Path: "/", - }, nil - } remoteFullPath := "" var remoteObj model.Obj var err, err2 error diff --git a/drivers/netease_music/driver.go b/drivers/netease_music/driver.go index b03c3b2cc..8f34bb98b 100644 --- a/drivers/netease_music/driver.go +++ b/drivers/netease_music/driver.go @@ -42,14 +42,14 @@ func (d *NeteaseMusic) Drop(ctx context.Context) error { return nil } -func (d *NeteaseMusic) Get(ctx context.Context, path string) (model.Obj, error) { - if path == "/" { - return &model.Object{ - IsFolder: true, - Path: path, - }, nil - } +func (d *NeteaseMusic) GetRoot(ctx context.Context) (model.Obj, error) { + return &model.Object{ + IsFolder: true, + Path: "/", + }, nil +} +func (d *NeteaseMusic) Get(ctx context.Context, path string) (model.Obj, error) { fragments := strings.Split(path, "/") if len(fragments) > 1 { fileName := fragments[1] diff --git a/drivers/strm/driver.go b/drivers/strm/driver.go index 010defa90..a7ffa9e35 100644 --- a/drivers/strm/driver.go +++ b/drivers/strm/driver.go @@ -89,14 +89,15 @@ func (d *Strm) Drop(ctx context.Context) error { return nil } +func (d *Strm) GetRoot(ctx context.Context) (model.Obj, error) { + return &model.Object{ + Name: "Root", + IsFolder: true, + Path: "/", + }, nil +} + func (d *Strm) Get(ctx context.Context, path string) (model.Obj, error) { - if utils.PathEqual(path, "/") { - return &model.Object{ - Name: "Root", - IsFolder: true, - Path: "/", - }, nil - } root, sub := d.getRootAndPath(path) dsts, ok := d.pathMap[root] if !ok { diff --git a/internal/driver/driver.go b/internal/driver/driver.go index 4a8e88255..7521e8d77 100644 --- a/internal/driver/driver.go +++ b/internal/driver/driver.go @@ -47,11 +47,6 @@ type Getter interface { Get(ctx context.Context, path string) (model.Obj, error) } -type GetObjInfo interface { - // GetObjInfo get file info by path - GetObjInfo(ctx context.Context, path string) (model.Obj, error) -} - //type Writer interface { // Mkdir // Move diff --git a/internal/op/fs.go b/internal/op/fs.go index ac8671037..cb9f54adb 100644 --- a/internal/op/fs.go +++ b/internal/op/fs.go @@ -5,7 +5,6 @@ import ( stderrors "errors" stdpath "path" "slices" - "strings" "time" "github.com/OpenListTeam/OpenList/v4/internal/driver" @@ -178,17 +177,6 @@ func Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, er path = utils.FixAndCleanPath(path) log.Debugf("op.Get %s", path) - // get the obj directly without list so that we can reduce the io - if g, ok := storage.(driver.Getter); ok { - obj, err := g.Get(ctx, path) - if err == nil { - return model.WrapObjName(obj), nil - } - if !errs.IsNotImplementError(err) && !errs.IsNotSupportError(err) { - return nil, errors.WithMessage(err, "failed to get obj") - } - } - // is root folder if utils.PathEqual(path, "/") { var rootObj model.Obj @@ -231,7 +219,28 @@ func Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, er // not root folder dir, name := stdpath.Split(path) - files, err := List(ctx, storage, dir, model.ListArgs{}) + key := Key(storage, dir) + if files, ok := listCache.Get(key); ok { + log.Debugf("use cache when list %s", dir) + for _, f := range files { + if f.GetName() == name { + return f, nil + } + } + } + + // get the obj directly without list so that we can reduce the io + if g, ok := storage.(driver.Getter); ok { + obj, err := g.Get(ctx, path) + if err == nil { + return model.WrapObjName(obj), nil + } + if !errs.IsNotImplementError(err) && !errs.IsNotSupportError(err) { + return nil, errors.WithMessage(err, "failed to get obj") + } + } + + files, err := List(ctx, storage, dir, model.ListArgs{Refresh: true}) if err != nil { return nil, errors.WithMessage(err, "failed get parent list") } @@ -261,32 +270,11 @@ func Link(ctx context.Context, storage driver.Driver, path string, args model.Li if storage.Config().CheckStatus && storage.GetStorage().Status != WORK { return nil, nil, errors.WithMessagef(errs.StorageNotInit, "storage status: %s", storage.GetStorage().Status) } - var ( - file model.Obj - err error - ) - // use cache directly - dir, name := stdpath.Split(stdpath.Join(storage.GetStorage().MountPath, path)) - if cacheFiles, ok := listCache.Get(strings.TrimSuffix(dir, "/")); ok { - for _, f := range cacheFiles { - if f.GetName() == name { - file = model.UnwrapObj(f) - break - } - } - } else { - if g, ok := storage.(driver.GetObjInfo); ok { - file, err = g.GetObjInfo(ctx, path) - } else { - file, err = GetUnwrap(ctx, storage, path) - } - } - if file == nil { - if err != nil { - return nil, nil, errors.WithMessage(err, "failed to get file") - } - return nil, nil, errors.WithStack(errs.ObjectNotFound) + file, err := GetUnwrap(ctx, storage, path) + if err != nil { + return nil, nil, errors.WithMessage(err, "failed to get file") } + if file.IsDir() { return nil, nil, errors.WithStack(errs.NotFile) }