package local import ( "io" "os" "path/filepath" stgtypes "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types" jcstypes "gitlink.org.cn/cloudream/jcs-pub/common/types" ) type DirReader struct { // 完整的根路径(包括ReadDir的path参数),比如包括了盘符 absRootPath string // ReadDir函数传递进来的path参数 rootJPath jcstypes.JPath init bool curEntries []dirEntry } func (r *DirReader) Next() (stgtypes.DirEntry, error) { if !r.init { info, err := os.Stat(r.absRootPath) if err != nil { return stgtypes.DirEntry{}, err } if !info.IsDir() { r.init = true return stgtypes.DirEntry{ Path: r.rootJPath, Size: info.Size(), ModTime: info.ModTime(), IsDir: false, }, nil } es, err := os.ReadDir(r.absRootPath) if err != nil { return stgtypes.DirEntry{}, err } for _, e := range es { r.curEntries = append(r.curEntries, dirEntry{ dir: jcstypes.JPath{}, entry: e, }) } r.init = true } if len(r.curEntries) == 0 { return stgtypes.DirEntry{}, io.EOF } entry := r.curEntries[0] r.curEntries = r.curEntries[1:] if entry.entry.IsDir() { es, err := os.ReadDir(filepath.Join(r.absRootPath, entry.dir.OSString(), entry.entry.Name())) if err != nil { return stgtypes.DirEntry{}, err } // 多个entry对象共享同一个JPath对象,但因为不会修改JPath,所以没问题 dir := entry.dir.Clone() dir.Push(entry.entry.Name()) for _, e := range es { r.curEntries = append(r.curEntries, dirEntry{ dir: dir, entry: e, }) } } info, err := entry.entry.Info() if err != nil { return stgtypes.DirEntry{}, err } p := r.rootJPath.ConcatNew(entry.dir) p.Push(entry.entry.Name()) if entry.entry.IsDir() { return stgtypes.DirEntry{ Path: p, Size: 0, ModTime: info.ModTime(), IsDir: true, }, nil } return stgtypes.DirEntry{ Path: p, Size: info.Size(), ModTime: info.ModTime(), IsDir: false, }, nil } func (r *DirReader) Close() { } type dirEntry struct { dir jcstypes.JPath entry os.DirEntry }