mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 增加文件复制功能
This commit is contained in:
parent
f4eead9cc2
commit
7719f028fb
@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/1Panel-dev/1Panel/app/dto"
|
"github.com/1Panel-dev/1Panel/app/dto"
|
||||||
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
"github.com/1Panel-dev/1Panel/utils/files"
|
"github.com/1Panel-dev/1Panel/utils/files"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"io"
|
"io"
|
||||||
@ -130,6 +131,24 @@ func (f FileService) MvFile(c dto.FileMove) error {
|
|||||||
if c.Type == "cut" {
|
if c.Type == "cut" {
|
||||||
return fo.Cut(c.OldPaths, c.NewPath)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
"github.com/mholt/archiver/v4"
|
"github.com/mholt/archiver/v4"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -116,6 +118,112 @@ func (f FileOp) Cut(oldPaths []string, dst string) error {
|
|||||||
return nil
|
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
|
type CompressType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
import { computed, ref, toRefs, watch, onUpdated } from 'vue';
|
import { computed, ref, toRefs, watch, onUpdated, onMounted } from 'vue';
|
||||||
|
|
||||||
interface Role {
|
interface Role {
|
||||||
r: boolean;
|
r: boolean;
|
||||||
@ -152,8 +152,16 @@ const changeMode = (val: String) => {
|
|||||||
getRoleNum(val[3], form.value.public);
|
getRoleNum(val[3], form.value.public);
|
||||||
};
|
};
|
||||||
|
|
||||||
onUpdated(() => {
|
const updateMode = () => {
|
||||||
form.value.mode = mode.value;
|
form.value.mode = mode.value;
|
||||||
changeMode(form.value.mode);
|
changeMode(form.value.mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
updateMode();
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateMode();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
width="30%"
|
width="30%"
|
||||||
@open="onOpen"
|
@open="onOpen"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
|
destory-on-close
|
||||||
>
|
>
|
||||||
<FileRole :mode="mode" @get-mode="getMode"></FileRole>
|
<FileRole :mode="mode" @get-mode="getMode"></FileRole>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
@ -87,6 +87,9 @@ const extension = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
if (fileForm.value) {
|
||||||
|
fileForm.value.resetFields();
|
||||||
|
}
|
||||||
em('close', open);
|
em('close', open);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,6 +67,9 @@ let addForm = reactive({ path: '', name: '', isDir: false, mode: 0o755, isLink:
|
|||||||
|
|
||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
if (fileForm.value) {
|
||||||
|
fileForm.value.resetFields();
|
||||||
|
}
|
||||||
em('close', open);
|
em('close', open);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,6 +71,9 @@ let form = ref<File.FileDeCompress>({ type: 'zip', dst: '', path: '' });
|
|||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
if (fileForm.value) {
|
||||||
|
fileForm.value.resetFields();
|
||||||
|
}
|
||||||
em('close', open);
|
em('close', open);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,6 +67,9 @@ const addForm = reactive({
|
|||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
if (fileForm.value) {
|
||||||
|
fileForm.value.resetFields();
|
||||||
|
}
|
||||||
em('close', open);
|
em('close', open);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,6 +75,9 @@ const rules = reactive<FormRules>({
|
|||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
if (fileForm.value) {
|
||||||
|
fileForm.value.resetFields();
|
||||||
|
}
|
||||||
em('close', open);
|
em('close', open);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,6 +60,9 @@ const rules = reactive<FormRules>({
|
|||||||
|
|
||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
if (fileForm.value) {
|
||||||
|
fileForm.value.resetFields();
|
||||||
|
}
|
||||||
em('close', false);
|
em('close', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const uploadRef = ref<UploadInstance>();
|
const uploadRef = ref<UploadInstance>();
|
||||||
// let loading = ref<Boolean>(false);
|
|
||||||
|
|
||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user