diff --git a/backend/app/service/file.go b/backend/app/service/file.go index cb4c4ae35..44f8eca2e 100644 --- a/backend/app/service/file.go +++ b/backend/app/service/file.go @@ -4,6 +4,7 @@ import ( "crypto/rand" "fmt" "github.com/1Panel-dev/1Panel/app/dto" + "github.com/1Panel-dev/1Panel/global" "github.com/1Panel-dev/1Panel/utils/files" "github.com/pkg/errors" "io" @@ -130,6 +131,24 @@ func (f FileService) MvFile(c dto.FileMove) error { if c.Type == "cut" { return fo.Cut(c.OldPaths, c.NewPath) } + var errs []error + if c.Type == "copy" { + for _, src := range c.OldPaths { + if err := fo.Copy(src, c.NewPath); err != nil { + errs = append(errs, err) + global.LOG.Errorf("copy file [%s] to [%s] failed, err: %s", src, c.NewPath, err.Error()) + } + } + } + + var errString string + for _, err := range errs { + errString += err.Error() + "\n" + } + if errString != "" { + return errors.New(errString) + } + return nil } diff --git a/backend/utils/files/file_op.go b/backend/utils/files/file_op.go index cf96d52a4..6ef469a73 100644 --- a/backend/utils/files/file_op.go +++ b/backend/utils/files/file_op.go @@ -4,11 +4,13 @@ import ( "context" "github.com/1Panel-dev/1Panel/global" "github.com/mholt/archiver/v4" + "github.com/pkg/errors" "github.com/spf13/afero" "io" "io/fs" "net/http" "os" + "path" "path/filepath" ) @@ -116,6 +118,112 @@ func (f FileOp) Cut(oldPaths []string, dst string) error { return nil } +func (f FileOp) Copy(src, dst string) error { + if src = path.Clean("/" + src); src == "" { + return os.ErrNotExist + } + + if dst = path.Clean("/" + dst); dst == "" { + return os.ErrNotExist + } + + if src == "/" || dst == "/" { + return os.ErrInvalid + } + + if dst == src { + return os.ErrInvalid + } + + info, err := f.Fs.Stat(src) + if err != nil { + return err + } + if info.IsDir() { + return f.CopyDir(src, dst) + } + + return f.CopyFile(src, dst) +} + +func (f FileOp) CopyDir(src, dst string) error { + srcInfo, err := f.Fs.Stat(src) + if err != nil { + return err + } + dstDir := filepath.Join(dst, srcInfo.Name()) + if err := f.Fs.MkdirAll(dstDir, srcInfo.Mode()); err != nil { + return err + } + + dir, _ := f.Fs.Open(src) + obs, err := dir.Readdir(-1) + if err != nil { + return err + } + var errs []error + + for _, obj := range obs { + fSrc := filepath.Join(src, obj.Name()) + fDst := filepath.Join(dstDir, obj.Name()) + + if obj.IsDir() { + err = f.CopyDir(fSrc, fDst) + if err != nil { + errs = append(errs, err) + } + } else { + err = f.CopyFile(fSrc, fDst) + if err != nil { + errs = append(errs, err) + } + } + } + + var errString string + for _, err := range errs { + errString += err.Error() + "\n" + } + + if errString != "" { + return errors.New(errString) + } + + return nil +} + +func (f FileOp) CopyFile(src, dst string) error { + srcFile, err := f.Fs.Open(src) + if err != nil { + return err + } + defer srcFile.Close() + + err = f.Fs.MkdirAll(filepath.Dir(dst), 0666) + if err != nil { + return err + } + + dstFile, err := f.Fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) + if err != nil { + return err + } + defer dstFile.Close() + + if _, err = io.Copy(dstFile, srcFile); err != nil { + return err + } + info, err := f.Fs.Stat(src) + if err != nil { + return err + } + if err = f.Fs.Chmod(dst, info.Mode()); err != nil { + return err + } + + return nil +} + type CompressType string const ( diff --git a/frontend/src/components/file-role/index.vue b/frontend/src/components/file-role/index.vue index 132fce99b..b153973b7 100644 --- a/frontend/src/components/file-role/index.vue +++ b/frontend/src/components/file-role/index.vue @@ -24,7 +24,7 @@ diff --git a/frontend/src/views/file-management/change-role/index.vue b/frontend/src/views/file-management/change-role/index.vue index 01aad5555..193df8104 100644 --- a/frontend/src/views/file-management/change-role/index.vue +++ b/frontend/src/views/file-management/change-role/index.vue @@ -6,6 +6,7 @@ width="30%" @open="onOpen" v-loading="loading" + destory-on-close >