feat: file aggregation and regular rename api (#3788)

* 增加文件聚合接口,将给定文件夹下所有文件移动到目标文件夹。

* 增加文件正则重命名接口。

---------

Co-authored-by: varg247 <varg247@qq.com>
This commit is contained in:
varg1714 2023-03-10 19:01:49 +08:00 committed by GitHub
parent d06c605421
commit 1091e1b740
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 152 additions and 0 deletions

View File

@ -3,12 +3,14 @@ package handles
import (
"fmt"
stdpath "path"
"regexp"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/fs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/internal/sign"
"github.com/alist-org/alist/v3/pkg/generic"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin"
@ -92,6 +94,93 @@ func FsMove(c *gin.Context) {
common.SuccessResp(c)
}
type RecursiveMoveReq struct {
SrcDir string `json:"src_dir"`
DstDir string `json:"dst_dir"`
}
func FsRecursiveMove(c *gin.Context) {
var req RecursiveMoveReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}
user := c.MustGet("user").(*model.User)
if !user.CanMove() {
common.ErrorResp(c, errs.PermissionDenied, 403)
return
}
srcDir, err := user.JoinPath(req.SrcDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
dstDir, err := user.JoinPath(req.DstDir)
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, false)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
// record the file path
filePathMap := make(map[model.Obj]string)
movingFiles := generic.NewQueue[model.Obj]()
for _, file := range rootFiles {
movingFiles.Push(file)
filePathMap[file] = srcDir
}
for !movingFiles.IsEmpty() {
movingFile := movingFiles.Pop()
movingFilePath := fmt.Sprintf("%s/%s", filePathMap[movingFile], movingFile.GetName())
if movingFile.IsDir() {
// directory, recursive move
subFilePath := movingFilePath
subFiles, err := fs.List(c, subFilePath, true)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
for _, subFile := range subFiles {
movingFiles.Push(subFile)
filePathMap[subFile] = subFilePath
}
} else {
if movingFilePath == dstDir {
// same directory, don't move
continue
}
// move
err := fs.Move(c, movingFilePath, dstDir, movingFiles.IsEmpty())
if err != nil {
common.ErrorResp(c, err, 500)
return
}
}
}
common.SuccessResp(c)
}
func FsCopy(c *gin.Context) {
var req MoveCopyReq
if err := c.ShouldBind(&req); err != nil {
@ -163,6 +252,67 @@ func FsRename(c *gin.Context) {
common.SuccessResp(c)
}
type RegexRenameReq struct {
SrcDir string `json:"src_dir"`
SrcNameRegex string `json:"src_name_regex"`
NewNameRegex string `json:"new_name_regex"`
}
func FsRegexRename(c *gin.Context) {
var req RegexRenameReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}
user := c.MustGet("user").(*model.User)
if !user.CanRename() {
common.ErrorResp(c, errs.PermissionDenied, 403)
return
}
reqPath, err := user.JoinPath(req.SrcDir)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
meta, err := op.GetNearestMeta(reqPath)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
return
}
}
c.Set("meta", meta)
srcRegexp, err := regexp.Compile(req.SrcNameRegex)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
files, err := fs.List(c, reqPath, false)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
for _, file := range files {
if srcRegexp.MatchString(file.GetName()) {
filePath := fmt.Sprintf("%s/%s", reqPath, file.GetName())
newFileName := srcRegexp.ReplaceAllString(file.GetName(), req.NewNameRegex)
if err := fs.Rename(c, filePath, newFileName); err != nil {
common.ErrorResp(c, err, 500)
return
}
}
}
common.SuccessResp(c)
}
type RemoveReq struct {
Dir string `json:"dir"`
Names []string `json:"names"`

View File

@ -126,7 +126,9 @@ func _fs(g *gin.RouterGroup) {
g.Any("/dirs", handles.FsDirs)
g.POST("/mkdir", handles.FsMkdir)
g.POST("/rename", handles.FsRename)
g.POST("/regex_rename", handles.FsRegexRename)
g.POST("/move", handles.FsMove)
g.POST("/recursive_move", handles.FsRecursiveMove)
g.POST("/copy", handles.FsCopy)
g.POST("/remove", handles.FsRemove)
g.PUT("/put", middlewares.FsUp, handles.FsStream)