Browse Source

feat: 增加文件复制功能

pull/18/head^2
zhengkunwang223 2 years ago
parent
commit
7719f028fb
  1. 19
      backend/app/service/file.go
  2. 108
      backend/utils/files/file_op.go
  3. 12
      frontend/src/components/file-role/index.vue
  4. 1
      frontend/src/views/file-management/change-role/index.vue
  5. 3
      frontend/src/views/file-management/compress/index.vue
  6. 3
      frontend/src/views/file-management/create/index.vue
  7. 3
      frontend/src/views/file-management/decompress/index.vue
  8. 3
      frontend/src/views/file-management/download/index.vue
  9. 3
      frontend/src/views/file-management/move/index.vue
  10. 3
      frontend/src/views/file-management/rename/index.vue
  11. 1
      frontend/src/views/file-management/upload/index.vue

19
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
}

108
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 (

12
frontend/src/components/file-role/index.vue

@ -24,7 +24,7 @@
</template>
<script setup lang="ts">
import { FormInstance } from 'element-plus';
import { computed, ref, toRefs, watch, onUpdated } from 'vue';
import { computed, ref, toRefs, watch, onUpdated, onMounted } from 'vue';
interface Role {
r: boolean;
@ -152,8 +152,16 @@ const changeMode = (val: String) => {
getRoleNum(val[3], form.value.public);
};
onUpdated(() => {
const updateMode = () => {
form.value.mode = mode.value;
changeMode(form.value.mode);
};
onUpdated(() => {
updateMode();
});
onMounted(() => {
updateMode();
});
</script>

1
frontend/src/views/file-management/change-role/index.vue

@ -6,6 +6,7 @@
width="30%"
@open="onOpen"
v-loading="loading"
destory-on-close
>
<FileRole :mode="mode" @get-mode="getMode"></FileRole>
<template #footer>

3
frontend/src/views/file-management/compress/index.vue

@ -87,6 +87,9 @@ const extension = computed(() => {
});
const handleClose = () => {
if (fileForm.value) {
fileForm.value.resetFields();
}
em('close', open);
};

3
frontend/src/views/file-management/create/index.vue

@ -67,6 +67,9 @@ let addForm = reactive({ path: '', name: '', isDir: false, mode: 0o755, isLink:
const em = defineEmits(['close']);
const handleClose = () => {
if (fileForm.value) {
fileForm.value.resetFields();
}
em('close', open);
};

3
frontend/src/views/file-management/decompress/index.vue

@ -71,6 +71,9 @@ let form = ref<File.FileDeCompress>({ type: 'zip', dst: '', path: '' });
const em = defineEmits(['close']);
const handleClose = () => {
if (fileForm.value) {
fileForm.value.resetFields();
}
em('close', open);
};

3
frontend/src/views/file-management/download/index.vue

@ -67,6 +67,9 @@ const addForm = reactive({
const em = defineEmits(['close']);
const handleClose = () => {
if (fileForm.value) {
fileForm.value.resetFields();
}
em('close', open);
};

3
frontend/src/views/file-management/move/index.vue

@ -75,6 +75,9 @@ const rules = reactive<FormRules>({
const em = defineEmits(['close']);
const handleClose = () => {
if (fileForm.value) {
fileForm.value.resetFields();
}
em('close', open);
};

3
frontend/src/views/file-management/rename/index.vue

@ -60,6 +60,9 @@ const rules = reactive<FormRules>({
const em = defineEmits(['close']);
const handleClose = () => {
if (fileForm.value) {
fileForm.value.resetFields();
}
em('close', false);
};

1
frontend/src/views/file-management/upload/index.vue

@ -32,7 +32,6 @@ const props = defineProps({
});
const uploadRef = ref<UploadInstance>();
// let loading = ref<Boolean>(false);
const em = defineEmits(['close']);
const handleClose = () => {

Loading…
Cancel
Save