diff --git a/pkg/filesystem/driver/onedrive/api.go b/pkg/filesystem/driver/onedrive/api.go index ca19426..989e239 100644 --- a/pkg/filesystem/driver/onedrive/api.go +++ b/pkg/filesystem/driver/onedrive/api.go @@ -26,6 +26,8 @@ const ( SmallFileSize uint64 = 4 * 1024 * 1024 // ChunkSize 分片上传分片大小 ChunkSize uint64 = 10 * 1024 * 1024 + // ListRetry 列取请求重试次数 + ListRetry = 1 ) // GetSourcePath 获取文件的绝对路径 @@ -59,6 +61,43 @@ func (client *Client) getRequestURL(api string) string { return base.String() } +// ListChildren 根据路径列取子对象 +func (client *Client) ListChildren(ctx context.Context, path string) ([]FileInfo, error) { + var requestURL string + dst := strings.TrimPrefix(path, "/") + if dst == "" { + requestURL = client.getRequestURL("me/drive/root/children") + } else { + requestURL = client.getRequestURL("me/drive/root:/" + dst + ":/children") + } + + res, err := client.requestWithStr(ctx, "GET", requestURL+"?$top=999999999", "", 200) + if err != nil { + retried := 0 + if v, ok := ctx.Value(fsctx.RetryCtx).(int); ok { + retried = v + } + if retried < ListRetry { + retried++ + util.Log().Debug("路径[%s]列取请求失败[%s],5秒钟后重试", path, err) + time.Sleep(time.Duration(5) * time.Second) + return client.ListChildren(context.WithValue(ctx, fsctx.RetryCtx, retried), path) + } + return nil, err + } + + var ( + decodeErr error + fileInfo ListResponse + ) + decodeErr = json.Unmarshal([]byte(res), &fileInfo) + if decodeErr != nil { + return nil, decodeErr + } + + return fileInfo.Value, nil +} + // Meta 根据资源ID或文件路径获取文件元信息 func (client *Client) Meta(ctx context.Context, id string, path string) (*FileInfo, error) { var requestURL string diff --git a/pkg/filesystem/driver/onedrive/handler.go b/pkg/filesystem/driver/onedrive/handler.go index f5bd4ca..e91ba2f 100644 --- a/pkg/filesystem/driver/onedrive/handler.go +++ b/pkg/filesystem/driver/onedrive/handler.go @@ -12,6 +12,9 @@ import ( "github.com/HFO4/cloudreve/pkg/serializer" "io" "net/url" + "path" + "path/filepath" + "strings" "time" ) @@ -22,8 +25,49 @@ type Driver struct { HTTPClient request.Client } -func (handler Driver) List(ctx context.Context, path string, recursive bool) ([]response.Object, error) { - panic("implement me") +// List 列取项目 +func (handler Driver) List(ctx context.Context, base string, recursive bool) ([]response.Object, error) { + base = strings.TrimPrefix(base, "/") + // 列取子项目 + objects, _ := handler.Client.ListChildren(ctx, base) + + // 获取真实的列取起始根目录 + rootPath := base + if realBase, ok := ctx.Value(fsctx.PathCtx).(string); ok { + rootPath = realBase + } else { + ctx = context.WithValue(ctx, fsctx.PathCtx, base) + } + + // 整理结果 + res := make([]response.Object, 0, len(objects)) + for _, object := range objects { + source := path.Join(base, object.Name) + rel, err := filepath.Rel(rootPath, source) + if err != nil { + continue + } + res = append(res, response.Object{ + Name: object.Name, + RelativePath: filepath.ToSlash(rel), + Source: source, + Size: object.Size, + IsDir: object.Folder != nil, + LastModify: time.Now(), + }) + } + + // 递归列取子目录 + if recursive { + for _, object := range objects { + if object.Folder != nil { + sub, _ := handler.List(ctx, path.Join(base, object.Name), recursive) + res = append(res, sub...) + } + } + } + + return res, nil } // Get 获取文件 diff --git a/pkg/filesystem/driver/onedrive/types.go b/pkg/filesystem/driver/onedrive/types.go index 3e016e4..fdf64d5 100644 --- a/pkg/filesystem/driver/onedrive/types.go +++ b/pkg/filesystem/driver/onedrive/types.go @@ -32,6 +32,16 @@ type FileInfo struct { Image imageInfo `json:"image"` ParentReference parentReference `json:"parentReference"` DownloadURL string `json:"@microsoft.graph.downloadUrl"` + File *file `json:"file"` + Folder *folder `json:"folder"` +} + +type file struct { + MimeType string `json:"mimeType"` +} + +type folder struct { + ChildCount int `json:"childCount"` } type imageInfo struct { @@ -83,6 +93,12 @@ type ThumbResponse struct { URL string `json:"url"` } +// ListResponse 列取子项目响应 +type ListResponse struct { + Value []FileInfo `json:"value"` + Context string `json:"@odata.context"` +} + // Chunk 文件分片 type Chunk struct { Offset int