1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 14:08:06 +08:00

feat: 增加文件下载功能

This commit is contained in:
zhengkunwang223 2022-09-05 16:25:26 +08:00
parent 04db6a8cf3
commit 16b9adfefe
14 changed files with 195 additions and 5 deletions

View File

@ -167,3 +167,16 @@ func (b *BaseApi) ChangeName(c *gin.Context) {
}
helper.SuccessWithData(c, nil)
}
func (b *BaseApi) Download(c *gin.Context) {
var req dto.FileDownload
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := fileService.Download(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

View File

@ -57,3 +57,9 @@ type FileRename struct {
OldName string
NewName string
}
type FileDownload struct {
Url string `json:"url" validate:"required"`
Path string `json:"path" validate:"required"`
Name string `json:"name" validate:"required"`
}

View File

@ -120,6 +120,11 @@ func (f FileService) ChangeName(c dto.FileRename) error {
return fo.Rename(c.OldName, c.NewName)
}
func (f FileService) Download(c dto.FileDownload) error {
fo := files.NewFileOp()
return fo.DownloadFile(c.Url, filepath.Join(c.Path, c.Name))
}
func getUuid() string {
b := make([]byte, 16)
io.ReadFull(rand.Reader, b)

View File

@ -26,6 +26,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
fileRouter.POST("/save", baseApi.SaveContent)
fileRouter.POST("/upload", baseApi.UploadFiles)
fileRouter.POST("/rename", baseApi.ChangeName)
fileRouter.POST("/download", baseApi.Download)
}
}

View File

@ -2,10 +2,12 @@ package files
import (
"context"
"github.com/1Panel-dev/1Panel/global"
"github.com/mholt/archiver/v4"
"github.com/spf13/afero"
"io"
"io/fs"
"net/http"
"os"
"path/filepath"
)
@ -81,6 +83,28 @@ func (f FileOp) Rename(oldName string, newName string) error {
return f.Fs.Rename(oldName, newName)
}
func (f FileOp) DownloadFile(url, dst string) error {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, err := os.Create(dst)
if err != nil {
panic(err)
}
defer out.Close()
go func() {
if _, err = io.Copy(out, resp.Body); err != nil {
global.LOG.Errorf("save download file [%s] error, err %s", dst, err.Error())
}
}()
return nil
}
type CompressType string
const (

View File

@ -63,6 +63,9 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
}
if file.IsSymlink {
file.LinkPath = GetSymlink(op.Path)
}
if op.Search != "" {
}
if op.Expand {
if file.IsDir {

View File

@ -69,4 +69,10 @@ export namespace File {
oldName: string;
newName: string;
}
export interface FileDownload {
path: string;
name: string;
url: string;
}
}

View File

@ -44,3 +44,7 @@ export const UploadFileData = (params: FormData) => {
export const RenameRile = (params: File.FileRename) => {
return http.post<File.File>('files/rename', params);
};
export const DownloadFile = (params: File.FileDownload) => {
return http.post<File.File>('files/download', params);
};

View File

@ -5,8 +5,6 @@
</template>
<script setup lang="ts">
import { defineProps } from 'vue';
const props = defineProps({
right: Boolean,
});

View File

@ -3,7 +3,7 @@ export enum ResultEnum {
ERROR = 500,
OVERDUE = 401,
FORBIDDEN = 403,
TIMEOUT = 10000,
TIMEOUT = 100000,
TYPE = 'success',
}

View File

@ -184,5 +184,21 @@ export default {
wRole: 'Write',
xRole: 'executable',
name: 'name',
compress: 'compress',
deCompress: 'Decompress',
compressType: 'compression format',
compressDst: 'compression path',
replace: 'Overwrite existing file',
compressSuccess: 'Compression successful',
deCompressSuccess: 'Decompression succeeded',
deCompressDst: 'Decompression path',
linkType: 'Link type',
softLink: 'soft link',
hardLink: 'hard link',
linkPath: 'Link path',
selectFile: 'Select file',
downloadSuccess: 'Download successful',
downloadUrl: 'download URL',
downloadStart: 'Download started!',
},
};

View File

@ -197,5 +197,8 @@ export default {
hardLink: '硬链接',
linkPath: '链接路径',
selectFile: '选择文件',
downloadSuccess: '下载成功',
downloadUrl: '下载地址',
downloadStart: '下载开始!',
},
};

View File

@ -0,0 +1,98 @@
<template>
<el-dialog v-model="open" :before-close="handleClose" :title="$t('file.download')" width="30%" @open="onOpen">
<el-form
ref="fileForm"
label-position="left"
:model="addForm"
label-width="100px"
:rules="rules"
v-loading="loading"
>
<el-form-item :label="$t('file.downloadUrl')" prop="url">
<el-input v-model="addForm.url" />
</el-form-item>
<el-form-item :label="$t('file.path')" prop="path">
<el-input v-model="addForm.path">
<template #append> <FileList :path="path" @choose="getPath"></FileList> </template
></el-input>
</el-form-item>
<el-form-item :label="$t('file.name')" prop="name">
<el-input v-model="addForm.name"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submit(fileForm)" :disabled="loading">{{
$t('commons.button.confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { DownloadFile } from '@/api/modules/files';
import { Rules } from '@/global/form-rues';
import i18n from '@/lang';
import { ElMessage, FormInstance, FormRules } from 'element-plus';
import { reactive, ref, toRefs } from 'vue';
const props = defineProps({
open: {
type: Boolean,
default: false,
},
path: {
type: String,
default: '',
},
});
const { open } = toRefs(props);
const fileForm = ref<FormInstance>();
const loading = ref(false);
const rules = reactive<FormRules>({
name: [Rules.requiredInput],
path: [Rules.requiredInput],
url: [Rules.requiredInput],
});
const addForm = reactive({
url: '',
path: '',
name: '',
});
const em = defineEmits(['close']);
const handleClose = () => {
em('close', open);
};
const getPath = (path: string) => {
addForm.path = path;
};
const onOpen = () => {
addForm.path = props.path;
};
const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (!valid) {
return;
}
loading.value = true;
DownloadFile(addForm)
.then(() => {
ElMessage.success(i18n.global.t('file.downloadStart'));
handleClose();
})
.finally(() => {
loading.value = false;
});
});
};
</script>

View File

@ -58,8 +58,8 @@
</template>
</el-dropdown>
<el-button type="primary" plain @click="openUpload"> {{ $t('file.upload') }}</el-button>
<el-button type="primary" plain> {{ $t('file.search') }}</el-button>
<el-button type="primary" plain> {{ $t('file.remoteFile') }}</el-button>
<!-- <el-button type="primary" plain> {{ $t('file.search') }}</el-button> -->
<el-button type="primary" plain @click="openDownload"> {{ $t('file.remoteFile') }}</el-button>
<!-- <el-button type="primary" plain> {{ $t('file.sync') }}</el-button>
<el-button type="primary" plain> {{ $t('file.terminal') }}</el-button>
<el-button type="primary" plain> {{ $t('file.shareList') }}</el-button> -->
@ -131,6 +131,7 @@
@close="closeRename"
></FileRename>
<Upload :open="uploadPage.open" :path="uploadPage.path" @close="closeUpload"></Upload>
<FileDown :open="downloadPage.open" :path="downloadPage.path" @close="closeDownload"></FileDown>
</el-row>
</LayoutContent>
</template>
@ -154,6 +155,7 @@ import FileRename from './file-rename/index.vue';
import { useDeleteData } from '@/hooks/use-delete-data';
import CodeEditor from './code-editor/index.vue';
import { ElMessage } from 'element-plus';
import FileDown from './file-down/index.vue';
let data = ref();
let selects = ref<any>([]);
@ -172,6 +174,7 @@ const editorPage = reactive({ open: false, content: '', loading: false });
const codeReq = reactive({ path: '', expand: false });
const uploadPage = reactive({ open: false, path: '' });
const renamePage = reactive({ open: false, path: '', oldName: '' });
const downloadPage = reactive({ open: false, path: '' });
const defaultProps = {
children: 'children',
@ -346,6 +349,16 @@ const closeUpload = () => {
search(req);
};
const openDownload = () => {
downloadPage.open = true;
downloadPage.path = req.path;
};
const closeDownload = () => {
downloadPage.open = false;
search(req);
};
const openRename = (item: File.File) => {
renamePage.open = true;
renamePage.path = req.path;