Skip to content

Commit d83fb2c

Browse files
committed
feat(toolbar): support recursive file listing
1 parent 72280d0 commit d83fb2c

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

server/handles/fsread.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package handles
22

33
import (
4+
"context"
45
"fmt"
56
stdpath "path"
67
"strings"
@@ -14,10 +15,12 @@ import (
1415
"github.com/OpenListTeam/OpenList/v4/internal/op"
1516
"github.com/OpenListTeam/OpenList/v4/internal/setting"
1617
"github.com/OpenListTeam/OpenList/v4/internal/sign"
18+
"github.com/OpenListTeam/OpenList/v4/pkg/generic"
1719
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
1820
"github.com/OpenListTeam/OpenList/v4/server/common"
1921
"github.com/gin-gonic/gin"
2022
"github.com/pkg/errors"
23+
log "github.com/sirupsen/logrus"
2124
)
2225

2326
type ListReq struct {
@@ -435,6 +438,12 @@ type FsOtherReq struct {
435438
Password string `json:"password" form:"password"`
436439
}
437440

441+
type RecurseListReq struct {
442+
Path string `json:"path" form:"path"`
443+
Refresh bool `json:"refresh" form:"refresh"`
444+
IntervalSec int `json:"interval_sec" form:"interval_sec"`
445+
}
446+
438447
func FsOther(c *gin.Context) {
439448
var req FsOtherReq
440449
if err := c.ShouldBind(&req); err != nil {
@@ -467,3 +476,79 @@ func FsOther(c *gin.Context) {
467476
}
468477
common.SuccessResp(c, res)
469478
}
479+
480+
func FsRecurseList(c *gin.Context) {
481+
var req RecurseListReq
482+
if err := c.ShouldBind(&req); err != nil {
483+
common.ErrorResp(c, err, 400)
484+
return
485+
}
486+
user := c.Request.Context().Value(conf.UserKey).(*model.User)
487+
reqPath, err := user.JoinPath(req.Path)
488+
if err != nil {
489+
common.ErrorResp(c, err, 403)
490+
return
491+
}
492+
meta, err := op.GetNearestMeta(reqPath)
493+
if err != nil {
494+
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
495+
common.ErrorResp(c, err, 500, true)
496+
return
497+
}
498+
}
499+
if !common.CanAccess(user, meta, reqPath, "") {
500+
common.ErrorStrResp(c, "password is incorrect or you have no permission", 403)
501+
return
502+
}
503+
if !user.CanWrite() && !common.CanWrite(meta, reqPath) && req.Refresh {
504+
common.ErrorStrResp(c, "Refresh without permission", 403)
505+
return
506+
}
507+
508+
go func() {
509+
ctx := context.Background()
510+
ctx = context.WithValue(ctx, conf.UserKey, user)
511+
ctx = context.WithValue(ctx, conf.MetaKey, meta)
512+
513+
queue := generic.NewQueue[string]()
514+
queue.Push(reqPath)
515+
516+
visited := make(map[string]bool)
517+
518+
for queue.Len() > 0 {
519+
currentPath := queue.Pop()
520+
521+
if visited[currentPath] {
522+
continue
523+
}
524+
visited[currentPath] = true
525+
526+
objs, err := fs.List(ctx, currentPath, &fs.ListArgs{
527+
Refresh: req.Refresh,
528+
WithStorageDetails: false,
529+
NoLog: true,
530+
})
531+
if err != nil {
532+
log.Warnf("FsRecurseList: failed to list %s: %+v", currentPath, err)
533+
continue
534+
}
535+
536+
for _, obj := range objs {
537+
if obj.IsDir() {
538+
subPath := stdpath.Join(currentPath, obj.GetName())
539+
if !visited[subPath] {
540+
queue.Push(subPath)
541+
}
542+
}
543+
}
544+
545+
if req.IntervalSec > 0 && queue.Len() > 0 {
546+
time.Sleep(time.Duration(req.IntervalSec) * time.Second)
547+
}
548+
}
549+
550+
log.Infof("FsRecurseList: completed recursion for path %s", reqPath)
551+
}()
552+
553+
common.SuccessResp(c)
554+
}

server/router.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ func _fs(g *gin.RouterGroup) {
220220
g.POST("/archive/decompress", handles.FsArchiveDecompress)
221221
// Direct upload (client-side upload to storage)
222222
g.POST("/get_direct_upload_info", middlewares.FsUp, handles.FsGetDirectUploadInfo)
223+
g.POST("/recurse_list", handles.FsRecurseList)
223224
}
224225

225226
func _task(g *gin.RouterGroup) {

0 commit comments

Comments
 (0)