diff --git a/pkg/filesystem/driver/cos/handler.go b/pkg/filesystem/driver/cos/handler.go index 0190d9816850191e2c6686aeef741e2fdc8e2d6c..18915e239ed3370e3e79608ce8cf533e864e02ab 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 53147a98423172d0a0061d894c9ae95456a42057..7d1a93c0971a0ebd74fe42b4fbb4a30ef1a8b988 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 16551c148a555010de47561ed91551fed1aeeb41..fedddd3e450c09b00f20a33754573479f5facf81 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 1b4774c9b91c84aa04f1641014823c511407ccfe..43a2ac046f845ca416791d80c0902c103eaa9eb9 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 74235968c4db5b93f70be66dcc07811abb24a387..c8de8e29a7df549976db23c46fd3625a463666c1 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 1c7ef13976da66cc4f8c57ddf73d58ebcabebc59..143882bdb9b3de7aa155e6851ff128532ef32c46 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 232e5818071a0b4db2a807a4fe0a643a5a1fb4c0..d342129cfed879000acca2fb281e02af5174eb5c 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 c4696b22c941d1828998e87a4b55d24025c5d259..c53148425633c722aae0ad61dcda31bf50b76b11 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 d6119db435c21b26db577a5c33e880aa5655e29a..652cdd03408a375eb3f694c7bd20657e5c6af3c9 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 d0b74fa1ac40e560f821a662a3b6d100087a380f..da060e0aa16b205d09321ee75883eb03489bb803 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 1defda486d2a20c08b0503899ef4d1a616f7ac4b..4b48030a3295baa1d7dd960d83677fb9ceb8e2b5 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)