fix: 上传备份文件名限制

This commit is contained in:
ssongliu 2023-03-08 15:33:43 +08:00 committed by ssongliu
parent bb104bb734
commit e1992de7af
11 changed files with 218 additions and 30 deletions

View File

@ -323,6 +323,34 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
}
}
// @Tags File
// @Summary Check file exist
// @Description 检测文件是否存在
// @Accept json
// @Param request body request.FilePathCheck true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/check [post]
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测文件 [path] 是否存在","formatEN":"Check whether file [path] exists"}
func (b *BaseApi) CheckFile(c *gin.Context) {
var req request.FilePathCheck
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if _, err := os.Stat(req.Path); err != nil && os.IsNotExist(err) {
helper.SuccessWithData(c, true)
return
}
helper.SuccessWithData(c, false)
}
// @Tags File
// @Summary Change file name
// @Description 修改文件名称

View File

@ -58,6 +58,10 @@ type FileRename struct {
NewName string `json:"newName" validate:"required"`
}
type FilePathCheck struct {
Path string `json:"path" validate:"required"`
}
type FileWget struct {
Url string `json:"url" validate:"required"`
Path string `json:"path" validate:"required"`

View File

@ -99,7 +99,7 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
})
if !hasTestSql {
_ = os.RemoveAll(dstDir)
return fmt.Errorf("no such file named test.sql in %s, err: %v", fileName, err)
return fmt.Errorf("no such file named test.sql in %s", fileName)
}
defer func() {
_ = os.RemoveAll(dstDir)

View File

@ -25,6 +25,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
fileRouter.POST("/decompress", baseApi.DeCompressFile)
fileRouter.POST("/content", baseApi.GetContent)
fileRouter.POST("/save", baseApi.SaveContent)
fileRouter.POST("/check", baseApi.CheckFile)
fileRouter.POST("/upload", baseApi.UploadFiles)
fileRouter.POST("/rename", baseApi.ChangeFileName)
fileRouter.POST("/wget", baseApi.WgetFile)

View File

@ -3857,6 +3857,48 @@ var doc = `{
}
}
},
"/files/check": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "检测文件是否存在",
"consumes": [
"application/json"
],
"tags": [
"File"
],
"summary": "Check file exist",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/request.FilePathCheck"
}
}
],
"responses": {
"200": {
"description": ""
}
},
"x-panel-log": {
"BeforeFuntions": [],
"bodyKeys": [
"path"
],
"formatEN": "Check whether file [path] exists",
"formatZH": "检测文件 [path] 是否存在",
"paramKeys": []
}
}
},
"/files/compress": {
"post": {
"security": [
@ -9603,10 +9645,6 @@ var doc = `{
},
"dto.Login": {
"type": "object",
"required": [
"name",
"password"
],
"properties": {
"authMethod": {
"type": "string"
@ -9627,11 +9665,6 @@ var doc = `{
},
"dto.MFALogin": {
"type": "object",
"required": [
"name",
"password",
"secret"
],
"properties": {
"authMethod": {
"type": "string"
@ -10959,6 +10992,9 @@ var doc = `{
"deleteBackup": {
"type": "boolean"
},
"deleteDB": {
"type": "boolean"
},
"detailId": {
"type": "integer"
},
@ -11159,11 +11195,15 @@ var doc = `{
"request.FileDownload": {
"type": "object",
"required": [
"compress",
"name",
"paths",
"type"
],
"properties": {
"compress": {
"type": "boolean"
},
"name": {
"type": "string"
},
@ -11244,6 +11284,17 @@ var doc = `{
}
}
},
"request.FilePathCheck": {
"type": "object",
"required": [
"path"
],
"properties": {
"path": {
"type": "string"
}
}
},
"request.FileRename": {
"type": "object",
"required": [

View File

@ -3843,6 +3843,48 @@
}
}
},
"/files/check": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "检测文件是否存在",
"consumes": [
"application/json"
],
"tags": [
"File"
],
"summary": "Check file exist",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/request.FilePathCheck"
}
}
],
"responses": {
"200": {
"description": ""
}
},
"x-panel-log": {
"BeforeFuntions": [],
"bodyKeys": [
"path"
],
"formatEN": "Check whether file [path] exists",
"formatZH": "检测文件 [path] 是否存在",
"paramKeys": []
}
}
},
"/files/compress": {
"post": {
"security": [
@ -9589,10 +9631,6 @@
},
"dto.Login": {
"type": "object",
"required": [
"name",
"password"
],
"properties": {
"authMethod": {
"type": "string"
@ -9613,11 +9651,6 @@
},
"dto.MFALogin": {
"type": "object",
"required": [
"name",
"password",
"secret"
],
"properties": {
"authMethod": {
"type": "string"
@ -10945,6 +10978,9 @@
"deleteBackup": {
"type": "boolean"
},
"deleteDB": {
"type": "boolean"
},
"detailId": {
"type": "integer"
},
@ -11145,11 +11181,15 @@
"request.FileDownload": {
"type": "object",
"required": [
"compress",
"name",
"paths",
"type"
],
"properties": {
"compress": {
"type": "boolean"
},
"name": {
"type": "string"
},
@ -11230,6 +11270,17 @@
}
}
},
"request.FilePathCheck": {
"type": "object",
"required": [
"path"
],
"properties": {
"path": {
"type": "string"
}
}
},
"request.FileRename": {
"type": "object",
"required": [

View File

@ -839,9 +839,6 @@ definitions:
type: string
password:
type: string
required:
- name
- password
type: object
dto.MFALogin:
properties:
@ -855,10 +852,6 @@ definitions:
type: string
secret:
type: string
required:
- name
- password
- secret
type: object
dto.MfaCredential:
properties:
@ -1723,6 +1716,8 @@ definitions:
type: integer
deleteBackup:
type: boolean
deleteDB:
type: boolean
detailId:
type: integer
forceDelete:
@ -1859,6 +1854,8 @@ definitions:
type: object
request.FileDownload:
properties:
compress:
type: boolean
name:
type: string
paths:
@ -1868,6 +1865,7 @@ definitions:
type:
type: string
required:
- compress
- name
- paths
- type
@ -1916,6 +1914,13 @@ definitions:
showHidden:
type: boolean
type: object
request.FilePathCheck:
properties:
path:
type: string
required:
- path
type: object
request.FileRename:
properties:
newName:
@ -5033,6 +5038,33 @@ paths:
formatEN: Batch delete dir or file [paths]
formatZH: 批量删除文件/文件夹 [paths]
paramKeys: []
/files/check:
post:
consumes:
- application/json
description: 检测文件是否存在
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/request.FilePathCheck'
responses:
"200":
description: ""
security:
- ApiKeyAuth: []
summary: Check file exist
tags:
- File
x-panel-log:
BeforeFuntions: []
bodyKeys:
- path
formatEN: Check whether file [path] exists
formatZH: 检测文件 [path] 是否存在
paramKeys: []
/files/compress:
post:
consumes:

View File

@ -51,6 +51,10 @@ export const SaveFileContent = (params: File.FileEdit) => {
return http.post<File.File>('files/save', params);
};
export const CheckFile = (path: string) => {
return http.post<boolean>('files/check', { path: path });
};
export const UploadFileData = (params: FormData, config: AxiosRequestConfig) => {
return http.upload<File.File>('files/upload', params, config);
};

View File

@ -82,7 +82,7 @@ import i18n from '@/lang';
import { UploadFile, UploadFiles, UploadInstance } from 'element-plus';
import { File } from '@/api/interface/file';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { BatchDeleteFile, GetUploadList, UploadFileData } from '@/api/modules/files';
import { BatchDeleteFile, CheckFile, GetUploadList, UploadFileData } from '@/api/modules/files';
import { loadBaseDir } from '@/api/modules/setting';
import { MsgError, MsgSuccess } from '@/utils/message';
@ -190,14 +190,26 @@ const handleClose = () => {
upVisiable.value = false;
};
const onSubmit = () => {
const onSubmit = async () => {
const formData = new FormData();
if (uploaderFiles.value.length !== 1) {
return;
}
if (uploaderFiles.value[0]!.raw != undefined) {
formData.append('file', uploaderFiles.value[0]!.raw);
if (!uploaderFiles.value[0]!.raw.name) {
MsgError(i18n.global.t('commons.msg.fileNameErr'));
return;
}
let reg = /^[a-zA-Z0-9\u4e00-\u9fa5]{1}[a-z:A-Z0-9_.\u4e00-\u9fa5-]{0,50}$/;
if (!reg.test(uploaderFiles.value[0]!.raw.name)) {
MsgError(i18n.global.t('commons.msg.fileNameErr'));
return;
}
const res = await CheckFile(baseDir.value + '/' + uploaderFiles.value[0]!.raw.name);
if (!res.data) {
MsgError(i18n.global.t('commons.msg.fileExist'));
return;
}
formData.append('file', uploaderFiles.value[0]!.raw);
let isOk = beforeAvatarUpload(uploaderFiles.value[0]!.raw);
if (!isOk) {
return;

View File

@ -93,6 +93,9 @@ export default {
backupSuccess: 'Backup Success',
unSupportType: 'Current file type is not supported!',
unSupportSize: 'The uploaded file exceeds {0}M, please confirm!',
fileExist: 'The file already exists in the current folder. Repeat uploading is not supported!',
fileNameErr:
'You can upload only files whose name contains 1 to 50 characters, including English, Chinese, digits, or periods (.-_)',
},
login: {
firstLogin: 'First login, please create an initial administrator user!',

View File

@ -99,6 +99,8 @@ export default {
notFound: '抱歉您访问的页面不存在',
unSupportType: '不支持当前文件类型',
unSupportSize: '上传文件超过 {0}M请确认',
fileExist: '当前文件夹已存在该文件不支持重复上传',
fileNameErr: '仅支持上传名称包含英文中文数字或者 .-_ ,长度 1-50 位的文件',
},
login: {
firstLogin: '首次登录请创建初始管理员用户',