diff --git a/backend/app/api/v1/file.go b/backend/app/api/v1/file.go index 0b862e191..f82d774da 100644 --- a/backend/app/api/v1/file.go +++ b/backend/app/api/v1/file.go @@ -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) +} diff --git a/backend/app/dto/file.go b/backend/app/dto/file.go index 7f3973c33..32b8a8eb5 100644 --- a/backend/app/dto/file.go +++ b/backend/app/dto/file.go @@ -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"` +} diff --git a/backend/app/service/file.go b/backend/app/service/file.go index 336acfa95..27333d070 100644 --- a/backend/app/service/file.go +++ b/backend/app/service/file.go @@ -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) diff --git a/backend/router/ro_file.go b/backend/router/ro_file.go index 7aa7453a1..64dd592ab 100644 --- a/backend/router/ro_file.go +++ b/backend/router/ro_file.go @@ -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) } } diff --git a/backend/utils/files/file_op.go b/backend/utils/files/file_op.go index a3c9203ff..3a88c3dca 100644 --- a/backend/utils/files/file_op.go +++ b/backend/utils/files/file_op.go @@ -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 ( diff --git a/backend/utils/files/fileinfo.go b/backend/utils/files/fileinfo.go index 38aac9c0d..6f5739c60 100644 --- a/backend/utils/files/fileinfo.go +++ b/backend/utils/files/fileinfo.go @@ -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 { diff --git a/frontend/src/api/interface/file.ts b/frontend/src/api/interface/file.ts index b45aded48..28e860123 100644 --- a/frontend/src/api/interface/file.ts +++ b/frontend/src/api/interface/file.ts @@ -69,4 +69,10 @@ export namespace File { oldName: string; newName: string; } + + export interface FileDownload { + path: string; + name: string; + url: string; + } } diff --git a/frontend/src/api/modules/files.ts b/frontend/src/api/modules/files.ts index b163d0624..39360d613 100644 --- a/frontend/src/api/modules/files.ts +++ b/frontend/src/api/modules/files.ts @@ -44,3 +44,7 @@ export const UploadFileData = (params: FormData) => { export const RenameRile = (params: File.FileRename) => { return http.post('files/rename', params); }; + +export const DownloadFile = (params: File.FileDownload) => { + return http.post('files/download', params); +}; diff --git a/frontend/src/components/bread-crumbs/bread-crumbs-item.vue b/frontend/src/components/bread-crumbs/bread-crumbs-item.vue index dfff05cfb..f6931379d 100644 --- a/frontend/src/components/bread-crumbs/bread-crumbs-item.vue +++ b/frontend/src/components/bread-crumbs/bread-crumbs-item.vue @@ -5,8 +5,6 @@ diff --git a/frontend/src/views/file-management/index.vue b/frontend/src/views/file-management/index.vue index 1338ccd1f..5e48132cc 100644 --- a/frontend/src/views/file-management/index.vue +++ b/frontend/src/views/file-management/index.vue @@ -58,8 +58,8 @@ {{ $t('file.upload') }} - {{ $t('file.search') }} - {{ $t('file.remoteFile') }} + + {{ $t('file.remoteFile') }} @@ -131,6 +131,7 @@ @close="closeRename" > + @@ -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([]); @@ -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;