From f7311f906b5906c663c14445b35cb6ed0398e483 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Fri, 24 Apr 2020 11:08:07 +0800 Subject: [PATCH] Feat: add List method to Handler interface / implement local.List --- pkg/filesystem/driver/cos/handler.go | 4 ++ pkg/filesystem/driver/local/handler.go | 41 +++++++++++++++++++++ pkg/filesystem/driver/local/handler_test.go | 10 +++++ pkg/filesystem/driver/onedrive/handler.go | 4 ++ pkg/filesystem/driver/oss/handler.go | 4 ++ pkg/filesystem/driver/qiniu/handler.go | 4 ++ pkg/filesystem/driver/remote/handler.go | 4 ++ pkg/filesystem/driver/upyun/handler.go | 4 ++ pkg/filesystem/filesystem.go | 5 ++- pkg/filesystem/response/common.go | 15 +++++++- pkg/filesystem/upload_test.go | 4 ++ 11 files changed, 97 insertions(+), 2 deletions(-) diff --git a/pkg/filesystem/driver/cos/handler.go b/pkg/filesystem/driver/cos/handler.go index 0190d98..18915e2 100644 --- a/pkg/filesystem/driver/cos/handler.go +++ b/pkg/filesystem/driver/cos/handler.go @@ -46,6 +46,10 @@ type Driver struct { HTTPClient request.Client } +func (handler Driver) List(ctx context.Context, path string) ([]response.Object, error) { + panic("implement me") +} + // CORS 创建跨域策略 func (handler Driver) CORS() error { _, err := handler.Client.Bucket.PutCORS(context.Background(), &cossdk.BucketPutCORSOptions{ diff --git a/pkg/filesystem/driver/local/handler.go b/pkg/filesystem/driver/local/handler.go index 53147a9..7d1a93c 100644 --- a/pkg/filesystem/driver/local/handler.go +++ b/pkg/filesystem/driver/local/handler.go @@ -23,6 +23,47 @@ type Driver struct { Policy *model.Policy } +// List 递归列取给定物理路径下所有文件 +func (handler Driver) List(ctx context.Context, path string) ([]response.Object, error) { + var res []response.Object + + // 取得起始路径 + root := util.RelativePath(filepath.FromSlash(path)) + + // 开始遍历路径下的文件、目录 + err := filepath.Walk(root, + func(path string, info os.FileInfo, err error) error { + // 跳过根目录 + if path == root { + return nil + } + + if err != nil { + util.Log().Warning("无法遍历目录 %s, %s", path, err) + return filepath.SkipDir + } + + // 将遍历对象的绝对路径转换为相对路径 + rel, err := filepath.Rel(root, path) + if err != nil { + return err + } + + res = append(res, response.Object{ + Name: info.Name(), + RelativePath: filepath.ToSlash(rel), + Source: path, + Size: uint64(info.Size()), + IsDir: info.IsDir(), + LastModify: info.ModTime(), + }) + + return nil + }) + + return res, err +} + // Get 获取文件内容 func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { // 打开文件 diff --git a/pkg/filesystem/driver/local/handler_test.go b/pkg/filesystem/driver/local/handler_test.go index 16551c1..fedddd3 100644 --- a/pkg/filesystem/driver/local/handler_test.go +++ b/pkg/filesystem/driver/local/handler_test.go @@ -2,6 +2,7 @@ package local import ( "context" + "fmt" model "github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/pkg/auth" "github.com/HFO4/cloudreve/pkg/conf" @@ -230,3 +231,12 @@ func TestHandler_Token(t *testing.T) { _, err := handler.Token(ctx, 10, "123") asserts.NoError(err) } + +func TestDriver_List(t *testing.T) { + //asserts := assert.New(t) + handler := Driver{} + ctx := context.Background() + + res, err := handler.List(ctx, "KKV") + fmt.Println(res, err) +} diff --git a/pkg/filesystem/driver/onedrive/handler.go b/pkg/filesystem/driver/onedrive/handler.go index 1b4774c..43a2ac0 100644 --- a/pkg/filesystem/driver/onedrive/handler.go +++ b/pkg/filesystem/driver/onedrive/handler.go @@ -22,6 +22,10 @@ type Driver struct { HTTPClient request.Client } +func (handler Driver) List(ctx context.Context, path string) ([]response.Object, error) { + panic("implement me") +} + // Get 获取文件 func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { // 获取文件源地址 diff --git a/pkg/filesystem/driver/oss/handler.go b/pkg/filesystem/driver/oss/handler.go index 7423596..c8de8e2 100644 --- a/pkg/filesystem/driver/oss/handler.go +++ b/pkg/filesystem/driver/oss/handler.go @@ -42,6 +42,10 @@ type Driver struct { HTTPClient request.Client } +func (handler *Driver) List(ctx context.Context, path string) ([]response.Object, error) { + panic("implement me") +} + type key int const ( diff --git a/pkg/filesystem/driver/qiniu/handler.go b/pkg/filesystem/driver/qiniu/handler.go index 1c7ef13..143882b 100644 --- a/pkg/filesystem/driver/qiniu/handler.go +++ b/pkg/filesystem/driver/qiniu/handler.go @@ -22,6 +22,10 @@ type Driver struct { Policy *model.Policy } +func (handler Driver) List(ctx context.Context, path string) ([]response.Object, error) { + panic("implement me") +} + // Get 获取文件 func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { // 给文件名加上随机参数以强制拉取 diff --git a/pkg/filesystem/driver/remote/handler.go b/pkg/filesystem/driver/remote/handler.go index 232e581..d342129 100644 --- a/pkg/filesystem/driver/remote/handler.go +++ b/pkg/filesystem/driver/remote/handler.go @@ -27,6 +27,10 @@ type Driver struct { AuthInstance auth.Auth } +func (handler Driver) List(ctx context.Context, path string) ([]response.Object, error) { + panic("implement me") +} + // getAPIUrl 获取接口请求地址 func (handler Driver) getAPIUrl(scope string, routes ...string) string { serverURL, err := url.Parse(handler.Policy.Server) diff --git a/pkg/filesystem/driver/upyun/handler.go b/pkg/filesystem/driver/upyun/handler.go index c4696b2..c531484 100644 --- a/pkg/filesystem/driver/upyun/handler.go +++ b/pkg/filesystem/driver/upyun/handler.go @@ -40,6 +40,10 @@ type Driver struct { Policy *model.Policy } +func (handler Driver) List(ctx context.Context, path string) ([]response.Object, error) { + panic("implement me") +} + // Get 获取文件 func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) { // 给文件名加上随机参数以强制拉取 diff --git a/pkg/filesystem/filesystem.go b/pkg/filesystem/filesystem.go index d6119db..652cdd0 100644 --- a/pkg/filesystem/filesystem.go +++ b/pkg/filesystem/filesystem.go @@ -41,7 +41,7 @@ type FileHeader interface { GetVirtualPath() string } -// Driver 存储策略适配器 +// Handler 存储策略适配器 type Handler interface { // 上传文件, dst为文件存储路径,size 为文件大小。上下文关闭 // 时,应取消上传并清理临时文件 @@ -64,6 +64,9 @@ type Handler interface { // Token 获取有效期为ttl的上传凭证和签名,同时回调会话有效期为sessionTTL Token(ctx context.Context, ttl int64, callbackKey string) (serializer.UploadCredential, error) + + // List 递归列取远程端path路径下文件、目录,不包含path本身,返回的对象路径以path作为起始根目录 + List(ctx context.Context, path string) ([]response.Object, error) } // FileSystem 管理文件的文件系统 diff --git a/pkg/filesystem/response/common.go b/pkg/filesystem/response/common.go index d0b74fa..da060e0 100644 --- a/pkg/filesystem/response/common.go +++ b/pkg/filesystem/response/common.go @@ -1,6 +1,9 @@ package response -import "io" +import ( + "io" + "time" +) // ContentResponse 获取文件内容类方法的通用返回值。 // 有些上传策略需要重定向, @@ -17,3 +20,13 @@ type RSCloser interface { io.ReadSeeker io.Closer } + +// Object 列出文件、目录时返回的对象 +type Object struct { + Name string + RelativePath string + Source string + Size uint64 + IsDir bool + LastModify time.Time +} diff --git a/pkg/filesystem/upload_test.go b/pkg/filesystem/upload_test.go index 1defda4..4b48030 100644 --- a/pkg/filesystem/upload_test.go +++ b/pkg/filesystem/upload_test.go @@ -26,6 +26,10 @@ type FileHeaderMock struct { testMock.Mock } +func (m FileHeaderMock) List(ctx context.Context, path string) ([]response.Object, error) { + panic("implement me") +} + func (m FileHeaderMock) Get(ctx context.Context, path string) (response.RSCloser, error) { args := m.Called(ctx, path) return args.Get(0).(response.RSCloser), args.Error(1)