mirror of https://github.com/Xhofe/alist
feat: empty folder clear API [ckip ci] (#4132)
* 增加清理空文件夹API * 修复嵌套文件夹删除Bug Author: varg247 <varg247@gmail.com> --------- Co-authored-by: varg247 <varg247@qq.com>pull/4053/head
parent
fdcad9c154
commit
46f9aefb04
|
@ -351,6 +351,105 @@ func FsRemove(c *gin.Context) {
|
||||||
common.SuccessResp(c)
|
common.SuccessResp(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RemoveEmptyDirectoryReq struct {
|
||||||
|
SrcDir string `json:"src_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func FsRemoveEmptyDirectory(c *gin.Context) {
|
||||||
|
var req RemoveEmptyDirectoryReq
|
||||||
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
|
common.ErrorResp(c, err, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user := c.MustGet("user").(*model.User)
|
||||||
|
if !user.CanRemove() {
|
||||||
|
common.ErrorResp(c, errs.PermissionDenied, 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
srcDir, err := user.JoinPath(req.SrcDir)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
meta, err := op.GetNearestMeta(srcDir)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
|
common.ErrorResp(c, err, 500, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Set("meta", meta)
|
||||||
|
|
||||||
|
rootFiles, err := fs.List(c, srcDir, &fs.ListArgs{})
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// record the file path
|
||||||
|
filePathMap := make(map[model.Obj]string)
|
||||||
|
// record the parent file
|
||||||
|
fileParentMap := make(map[model.Obj]model.Obj)
|
||||||
|
// removing files
|
||||||
|
removingFiles := generic.NewQueue[model.Obj]()
|
||||||
|
// removed files
|
||||||
|
removedFiles := make(map[string]bool)
|
||||||
|
for _, file := range rootFiles {
|
||||||
|
if !file.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
removingFiles.Push(file)
|
||||||
|
filePathMap[file] = srcDir
|
||||||
|
}
|
||||||
|
|
||||||
|
for !removingFiles.IsEmpty() {
|
||||||
|
|
||||||
|
removingFile := removingFiles.Pop()
|
||||||
|
removingFilePath := fmt.Sprintf("%s/%s", filePathMap[removingFile], removingFile.GetName())
|
||||||
|
|
||||||
|
if removedFiles[removingFilePath] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
subFiles, err := fs.List(c, removingFilePath, &fs.ListArgs{Refresh: true})
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(subFiles) == 0 {
|
||||||
|
// remove empty directory
|
||||||
|
err = fs.Remove(c, removingFilePath)
|
||||||
|
removedFiles[removingFilePath] = true
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// recheck parent folder
|
||||||
|
parentFile, exist := fileParentMap[removingFile]
|
||||||
|
if exist {
|
||||||
|
removingFiles.Push(parentFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// recursive remove
|
||||||
|
for _, subFile := range subFiles {
|
||||||
|
if !subFile.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
removingFiles.Push(subFile)
|
||||||
|
filePathMap[subFile] = removingFilePath
|
||||||
|
fileParentMap[subFile] = removingFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SuccessResp(c)
|
||||||
|
}
|
||||||
|
|
||||||
// Link return real link, just for proxy program, it may contain cookie, so just allowed for admin
|
// Link return real link, just for proxy program, it may contain cookie, so just allowed for admin
|
||||||
func Link(c *gin.Context) {
|
func Link(c *gin.Context) {
|
||||||
var req MkdirOrLinkReq
|
var req MkdirOrLinkReq
|
||||||
|
|
|
@ -131,6 +131,7 @@ func _fs(g *gin.RouterGroup) {
|
||||||
g.POST("/recursive_move", handles.FsRecursiveMove)
|
g.POST("/recursive_move", handles.FsRecursiveMove)
|
||||||
g.POST("/copy", handles.FsCopy)
|
g.POST("/copy", handles.FsCopy)
|
||||||
g.POST("/remove", handles.FsRemove)
|
g.POST("/remove", handles.FsRemove)
|
||||||
|
g.POST("/remove_empty_directory", handles.FsRemoveEmptyDirectory)
|
||||||
g.PUT("/put", middlewares.FsUp, handles.FsStream)
|
g.PUT("/put", middlewares.FsUp, handles.FsStream)
|
||||||
g.PUT("/form", middlewares.FsUp, handles.FsForm)
|
g.PUT("/form", middlewares.FsUp, handles.FsForm)
|
||||||
g.POST("/link", middlewares.AuthAdmin, handles.Link)
|
g.POST("/link", middlewares.AuthAdmin, handles.Link)
|
||||||
|
|
Loading…
Reference in New Issue