diff --git a/GinSkeleton/api_doc.md b/GinSkeleton/api_doc.md index 6d08c97..60034f4 100644 --- a/GinSkeleton/api_doc.md +++ b/GinSkeleton/api_doc.md @@ -239,4 +239,140 @@ type|form-data|string|必填|"summary"/"decoration"/"correction"/"extension"/"tr }, "msg": "Success" } -``` \ No newline at end of file +``` +#### 创建文件 +> *post*,/admin/file/file_creat + +参数字段|参数属性|类型|选项 +---|---|---|---|--- +user_name|form-data|string|必填 +file_name|form-data|string|必填 +file_path|form-data|string|必填 + +> 返回示例: +```json +{ +{ + "code": 200, + "data": "文件创建成功", + "msg": "Success" +} +} +``` +#### 创建文件夹 +> *post*,/admin/file/folder_creat + +参数字段|参数属性|类型|选项 +---|---|---|---|--- +user_name|form-data|string|必填 +folder_name|form-data|string|必填 +folder_path|form-data|string|必填 + +> 返回示例: +```json +{ +{ + "code": 200, + "data": "文件夹创建成功", + "msg": "Success" +} +} +``` +#### 打开文件 +> *post*,/admin/file/file_get + +参数字段|参数属性|类型|选项 +---|---|---|---|--- +user_name|form-data|string|必填 +file_name|form-data|string|必填 +file_path|form-data|string|必填 + +> 返回示例: +```json +{ +{ + "code": 200, + "data": "文件获取成功", + "msg": "Success" +} +} +``` +#### 文件重命名 +> *post*,/admin/file/file_rename + +参数字段|参数属性|类型|选项 +---|---|---|---|--- +user_name|form-data|string|必填 +file_name|form-data|string|必填 +file_path|form-data|string|必填 +newname|form-data|string|必填 + +> 返回示例: +```json +{ +{ + "code": 200, + "data": "文件重命名成功", + "msg": "Success" +} +} +``` +#### 移动文件 +> *post*,/admin/file/file_move + +参数字段|参数属性|类型|选项 +---|---|---|---|--- +user_name|form-data|string|必填 +file_name|form-data|string|必填 +file_path|form-data|string|必填 +newpath|form-data|string|必填 + +> 返回示例: +```json +{ +{ + "code": 200, + "data": "文件移动成功", + "msg": "Success" +} +} +``` +#### 保存文件 +> *post*,/admin/file/file_save + +参数字段|参数属性|类型|选项 +---|---|---|---|--- +user_name|form-data|string|必填 +file_name|form-data|string|必填 +save_path|form-data|string|必填 +file_data|form-data|string|必填 + +> 返回示例: +```json +{ +{ + "code": 200, + "data": "文件保存成功", + "msg": "Success" +} +} +``` +#### 删除文件 +> *post*,/admin/file/file_delete + +参数字段|参数属性|类型|选项 +---|---|---|---|--- +user_name|form-data|string|必填 +file_name|form-data|string|必填 +file_path|form-data|string|必填 + +> 返回示例: +```json +{ +{ + "code": 200, + "data": "文件删除成功", + "msg": "Success" +} +} +``` \ No newline at end of file diff --git a/GinSkeleton/app/global/consts/consts.go b/GinSkeleton/app/global/consts/consts.go index c8e36c8..b6884fc 100644 --- a/GinSkeleton/app/global/consts/consts.go +++ b/GinSkeleton/app/global/consts/consts.go @@ -54,6 +54,14 @@ const ( CurdLogoutFailMsg string = "登出失败" CurdPublicKeyFailCode int = -400209 CurdPublicKeyFailMsg string = "密钥获取失败" + CurdFilePathErrorCode int = -400210 + CurdFilePathErrorMsg string = "文件路径错误" + CurdFileNotExistCode int = -400211 + CurdFileNotExistMsg string = "文件不存在" + CurdFileUploadErrorCode int = -400212 + CurdFileUploadErrorMsg string = "文件上传失败" + CurdFileTypeErrorCode int = -400213 + CurdFileTypeErrorMsg string = "文件类型错误" //文件上传 FilesUploadFailCode int = -400250 FilesUploadFailMsg string = "文件上传失败, 获取上传文件发生错误!" diff --git a/GinSkeleton/app/http/controller/web/file_controller.go b/GinSkeleton/app/http/controller/web/file_controller.go new file mode 100644 index 0000000..83338ce --- /dev/null +++ b/GinSkeleton/app/http/controller/web/file_controller.go @@ -0,0 +1,209 @@ +package web + +import ( + "fmt" + "goskeleton/app/global/consts" + "goskeleton/app/service/file" + "goskeleton/app/utils/response" + "os" + + "github.com/gin-gonic/gin" +) + +type File struct { +} + +// 创建文件 +func (f *File) Creat(context *gin.Context) { + //从context获得路径和文件名,并拼接获得最终文件路径 + user_name := context.GetString(consts.ValidatorPrefix + "user_name") + file_Path := context.GetString(consts.ValidatorPrefix + "file_path") + file_Name := context.GetString(consts.ValidatorPrefix + "file_name") + final_Path := fmt.Sprintf("%s/%s.docx", file_Path, file_Name) + + //file, err := os.Create(final_Path) + if err := file.CreateFile(user_name, final_Path); err != nil { + response.Fail(context, consts.CurdCreatFailCode, consts.CurdCreatFailMsg, err.Error()) + return + } + + // 文件创建成功,返回成功响应给客户端 + response.Success(context, consts.CurdStatusOkMsg, "文件创建成功") +} + +// 创建文件夹 +func (f *File) FolderCreat(context *gin.Context) { + //从context获得路径和文件夹名,并拼接获得最终文件夹路径 + user_name := context.GetString(consts.ValidatorPrefix + "user_name") + folder_Path := context.GetString(consts.ValidatorPrefix + "folder_path") + folder_Name := context.GetString(consts.ValidatorPrefix + "folder_name") + final_Path := fmt.Sprintf("%s/%s", folder_Path, folder_Name) + + if err := file.CreateFolder(user_name, final_Path); err != nil { + response.Fail(context, consts.CurdCreatFailCode, consts.CurdCreatFailMsg, err.Error()) + return + } + + // 文件创建成功,返回成功响应给客户端 + response.Success(context, consts.CurdStatusOkMsg, "文件夹创建成功") +} + +// 打开文件 +func (f *File) Get(context *gin.Context) { + //从context获得路径和文件名,并拼接获得最终文件路径 + user_name := context.GetString(consts.ValidatorPrefix + "user_name") + file_Path := context.GetString(consts.ValidatorPrefix + "file_path") + file_Name := context.GetString(consts.ValidatorPrefix + "file_name") + final_Path := fmt.Sprintf("%s/%s.docx", file_Path, file_Name) + + fileObj, err := file.GetFile(user_name, final_Path) + if err != nil { + // 根据不同的错误类型,返回更具体、合适的错误响应给客户端 + switch err := err.(type) { + case *os.PathError: + //文件路径错误 + response.Fail(context, consts.CurdFilePathErrorCode, consts.CurdFilePathErrorMsg, err.Error()) + default: + if err == os.ErrNotExist { + //文件不存在错误 + response.Fail(context, consts.CurdFileNotExistCode, consts.CurdFileNotExistMsg, err.Error()) + } + + } + return + } + defer fileObj.Close() // 确保文件使用完后被关闭 + + // 文件获取成功,返回成功响应给客户端 + response.Success(context, consts.CurdStatusOkMsg, "文件获取成功") +} + +// 文件重命名 +func (f *File) Rename(context *gin.Context) { + //从context获得路径和文件名,并拼接获得最终文件路径 + user_name := context.GetString(consts.ValidatorPrefix + "user_name") + file_Path := context.GetString(consts.ValidatorPrefix + "file_path") + file_Name := context.GetString(consts.ValidatorPrefix + "file_name") + final_Path := fmt.Sprintf("%s/%s.docx", file_Path, file_Name) + + //old_Name := context.GetString(consts.ValidatorPrefix + "oldname") + new_Name := context.GetString(consts.ValidatorPrefix + "newname") + new_finalpath := fmt.Sprintf("%s/%s.docx", file_Path, new_Name) + + err := file.FileRename(user_name, final_Path, new_finalpath) + if err != nil { + // 根据不同的错误类型,返回更具体、合适的错误响应给客户端 + switch err := err.(type) { + case *os.PathError: + //文件路径错误 + response.Fail(context, consts.CurdFilePathErrorCode, consts.CurdFilePathErrorMsg, err.Error()) + default: + if err == os.ErrNotExist { + //文件不存在错误 + response.Fail(context, consts.CurdFileNotExistCode, consts.CurdFileNotExistMsg, err.Error()) + } + + } + return + } + + // 文件重命名成功,返回成功响应给客户端 + response.Success(context, consts.CurdStatusOkMsg, "文件重命名成功") +} + +// 文件移动 +func (f *File) Move(context *gin.Context) { + //从context获得路径和文件名,并拼接获得最终文件路径 + user_name := context.GetString(consts.ValidatorPrefix + "user_name") + file_Path := context.GetString(consts.ValidatorPrefix + "file_path") + file_Name := context.GetString(consts.ValidatorPrefix + "file_name") + final_Path := fmt.Sprintf("%s/%s.docx", file_Path, file_Name) + + //old_Name := context.GetString(consts.ValidatorPrefix + "oldname") + new_Path := context.GetString(consts.ValidatorPrefix + "newpath") + new_finalpath := fmt.Sprintf("%s/%s.docx", new_Path, file_Name) + + err := file.FileMove(user_name, final_Path, new_finalpath) + if err != nil { + // 根据不同的错误类型,返回更具体、合适的错误响应给客户端 + switch err := err.(type) { + case *os.PathError: + //文件路径错误 + response.Fail(context, consts.CurdFilePathErrorCode, consts.CurdFilePathErrorMsg, err.Error()) + default: + if err == os.ErrNotExist { + //文件不存在错误 + response.Fail(context, consts.CurdFileNotExistCode, consts.CurdFileNotExistMsg, err.Error()) + } + + } + return + } + + // 文件移动成功,返回成功响应给客户端 + response.Success(context, consts.CurdStatusOkMsg, "文件移动成功") +} + +// 文件保存 +func (f *File) Save(context *gin.Context) { + //从context获得路径和文件名,并拼接获得最终文件路径 + user_name := context.GetString(consts.ValidatorPrefix + "user_name") + Save_path := context.GetString(consts.ValidatorPrefix + "save_path") + file_Name := context.GetString(consts.ValidatorPrefix + "file_name") + final_savePath := fmt.Sprintf("%s/%s.docx", Save_path, file_Name) + + fileDataBase64 := context.PostForm("file_data") + if fileDataBase64 == "" { + response.Fail(context, consts.CurdFileNotExistCode, consts.CurdFileNotExistMsg, nil) + return + } + + err := file.FileSave(user_name, final_savePath, fileDataBase64) + if err != nil { + // 根据不同的错误类型,返回更具体、合适的错误响应给客户端 + switch err := err.(type) { + case *os.PathError: + //文件路径错误 + response.Fail(context, consts.CurdFilePathErrorCode, consts.CurdFilePathErrorMsg, err.Error()) + default: + if err == os.ErrNotExist { + //文件不存在错误 + response.Fail(context, consts.CurdFileNotExistCode, consts.CurdFileNotExistMsg, err.Error()) + } + + } + return + } + + // 文件保存成功,返回成功响应给客户端 + response.Success(context, consts.CurdStatusOkMsg, "文件保存成功") +} + +// 文件删除 +func (f *File) Delete(context *gin.Context) { + // 从context获得用户名、文件路径和文件名,并拼接获得最终文件路径 + user_name := context.GetString(consts.ValidatorPrefix + "user_name") + file_Path := context.GetString(consts.ValidatorPrefix + "file_path") + file_Name := context.GetString(consts.ValidatorPrefix + "file_name") + final_Path := fmt.Sprintf("%s/%s.docx", file_Path, file_Name) + + err := file.FileDe(user_name, final_Path) + if err != nil { + // 根据不同的错误类型,返回更具体、合适的错误响应给客户端 + switch err := err.(type) { + case *os.PathError: + //文件路径错误 + response.Fail(context, consts.CurdFilePathErrorCode, consts.CurdFilePathErrorMsg, err.Error()) + default: + if err == os.ErrNotExist { + //文件不存在错误 + response.Fail(context, consts.CurdFileNotExistCode, consts.CurdFileNotExistMsg, err.Error()) + } + + } + return + } + + // 文件删除成功,返回成功响应给客户端 + response.Success(context, consts.CurdStatusOkMsg, "文件删除成功") +} diff --git a/GinSkeleton/app/http/validator/common/register_validator/web_register_validator.go b/GinSkeleton/app/http/validator/common/register_validator/web_register_validator.go index 92ff849..01384db 100644 --- a/GinSkeleton/app/http/validator/common/register_validator/web_register_validator.go +++ b/GinSkeleton/app/http/validator/common/register_validator/web_register_validator.go @@ -6,9 +6,10 @@ import ( "goskeleton/app/http/validator/common/upload_files" "goskeleton/app/http/validator/common/websocket" "goskeleton/app/http/validator/web/ai_doc.go" + "goskeleton/app/http/validator/web/ai_layout" "goskeleton/app/http/validator/web/ai_recognition" + "goskeleton/app/http/validator/web/file" "goskeleton/app/http/validator/web/users" - "goskeleton/app/http/validator/web/ai_layout" ) // 各个业务模块验证器必须进行注册(初始化),程序启动时会自动加载到容器 @@ -63,5 +64,28 @@ func WebRegisterValidator() { containers.Set(key, ai_layout.StyleGenerate{}) key = consts.ValidatorPrefix + "LayoutGenerate" containers.Set(key, ai_layout.LayoutGenerate{}) - + + //文件相关操作 + //创建文件 + key = consts.ValidatorPrefix + "FileCreat" + containers.Set(key, file.FileCreat{}) + //创建文件夹 + key = consts.ValidatorPrefix + "FolderCreat" + containers.Set(key, file.FolderCreat{}) + //打开文件 + key = consts.ValidatorPrefix + "FileGet" + containers.Set(key, file.FileGet{}) + //文件重命名 + key = consts.ValidatorPrefix + "FileRename" + containers.Set(key, file.FileRename{}) + //移动文件 + key = consts.ValidatorPrefix + "FileMove" + containers.Set(key, file.FileMove{}) + //保存文件 + key = consts.ValidatorPrefix + "FileSave" + containers.Set(key, file.FileSave{}) + //删除文件 + key = consts.ValidatorPrefix + "FileDelete" + containers.Set(key, file.FileDelete{}) + } diff --git a/GinSkeleton/app/http/validator/web/file/FileDelete.go b/GinSkeleton/app/http/validator/web/file/FileDelete.go new file mode 100644 index 0000000..1b6863e --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/FileDelete.go @@ -0,0 +1,37 @@ +package file + +import ( + "goskeleton/app/global/consts" + "goskeleton/app/http/controller/web" + "goskeleton/app/http/validator/core/data_transfer" + "goskeleton/app/utils/response" + + "github.com/gin-gonic/gin" +) + +type FileDelete struct { + // 表单参数验证结构体支持匿名结构体嵌套 + BaseField + FileInfo +} + +// 验证器语法,参见 Register.go文件,有详细说明 + +func (f FileDelete) CheckParams(context *gin.Context) { + + //1.基本的验证规则没有通过 + if err := context.ShouldBind(&f); err != nil { + response.ValidatorError(context, err) + return + } + + // 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值 + extraAddBindDataContext := data_transfer.DataAddContext(f, consts.ValidatorPrefix, context) + if extraAddBindDataContext == nil { + response.ErrorSystem(context, "FileDelete表单验证器json化失败", "") + } else { + // 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性 + (&web.File{}).Delete(extraAddBindDataContext) + } + +} diff --git a/GinSkeleton/app/http/validator/web/file/FileGet.go b/GinSkeleton/app/http/validator/web/file/FileGet.go new file mode 100644 index 0000000..9489c09 --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/FileGet.go @@ -0,0 +1,37 @@ +package file + +import ( + "goskeleton/app/global/consts" + "goskeleton/app/http/controller/web" + "goskeleton/app/http/validator/core/data_transfer" + "goskeleton/app/utils/response" + + "github.com/gin-gonic/gin" +) + +type FileGet struct { + // 表单参数验证结构体支持匿名结构体嵌套 + BaseField + FileInfo +} + +// 验证器语法,参见 Register.go文件,有详细说明 + +func (f FileGet) CheckParams(context *gin.Context) { + + //1.基本的验证规则没有通过 + if err := context.ShouldBind(&f); err != nil { + response.ValidatorError(context, err) + return + } + + // 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值 + extraAddBindDataContext := data_transfer.DataAddContext(f, consts.ValidatorPrefix, context) + if extraAddBindDataContext == nil { + response.ErrorSystem(context, "FileGet表单验证器json化失败", "") + } else { + // 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性 + (&web.File{}).Get(extraAddBindDataContext) + } + +} diff --git a/GinSkeleton/app/http/validator/web/file/FileRename.go b/GinSkeleton/app/http/validator/web/file/FileRename.go new file mode 100644 index 0000000..4e25563 --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/FileRename.go @@ -0,0 +1,38 @@ +package file + +import ( + "goskeleton/app/global/consts" + "goskeleton/app/http/controller/web" + "goskeleton/app/http/validator/core/data_transfer" + "goskeleton/app/utils/response" + + "github.com/gin-gonic/gin" +) + +type FileRename struct { + // 表单参数验证结构体支持匿名结构体嵌套 + BaseField + FileInfo + Filename +} + +// 验证器语法,参见 Register.go文件,有详细说明 + +func (f FileRename) CheckParams(context *gin.Context) { + + //1.基本的验证规则没有通过 + if err := context.ShouldBind(&f); err != nil { + response.ValidatorError(context, err) + return + } + + // 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值 + extraAddBindDataContext := data_transfer.DataAddContext(f, consts.ValidatorPrefix, context) + if extraAddBindDataContext == nil { + response.ErrorSystem(context, "FileRename表单验证器json化失败", "") + } else { + // 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性 + (&web.File{}).Rename(extraAddBindDataContext) + } + +} diff --git a/GinSkeleton/app/http/validator/web/file/FileSave.go b/GinSkeleton/app/http/validator/web/file/FileSave.go new file mode 100644 index 0000000..1bd54e3 --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/FileSave.go @@ -0,0 +1,50 @@ +package file + +import ( + "goskeleton/app/global/consts" + "goskeleton/app/http/controller/web" + "goskeleton/app/http/validator/core/data_transfer" + "goskeleton/app/utils/response" + + "github.com/gin-gonic/gin" +) + +type FileSave struct { + // 表单参数验证结构体支持匿名结构体嵌套 + BaseField + FileUpload +} + +// 验证器语法,参见 Register.go文件,有详细说明 + +func (f FileSave) CheckParams(context *gin.Context) { + + //1.基本的验证规则没有通过 + if err := context.ShouldBind(&f); err != nil { + response.ValidatorError(context, err) + return + } + // 尝试获取上传的文件,检查文件是否存在 + //file, header, err := context.Request.FormFile("file") + //if err != nil { + // response.Fail(context, consts.CurdFileUploadErrorCode, consts.CurdFileUploadErrorMsg, "文件不存在或获取文件出错") + // return + //} + //defer file.Close() + + // 对文件名后缀进行额外校验,确保是.docx文件(假设只保存该类型文件) + //if filepath.Ext(header.Filename) != ".docx" { + // response.Fail(context, consts.CurdFileTypeErrorCode, consts.CurdFileTypeErrorMsg, "只支持上传.docx文件") + // return + //} + + // 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值 + extraAddBindDataContext := data_transfer.DataAddContext(f, consts.ValidatorPrefix, context) + if extraAddBindDataContext == nil { + response.ErrorSystem(context, "FileSave表单验证器json化失败", "") + } else { + // 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性 + (&web.File{}).Save(extraAddBindDataContext) + } + +} diff --git a/GinSkeleton/app/http/validator/web/file/Filecreat.go b/GinSkeleton/app/http/validator/web/file/Filecreat.go new file mode 100644 index 0000000..d2d6763 --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/Filecreat.go @@ -0,0 +1,37 @@ +package file + +import ( + "goskeleton/app/global/consts" + "goskeleton/app/http/controller/web" + "goskeleton/app/http/validator/core/data_transfer" + "goskeleton/app/utils/response" + + "github.com/gin-gonic/gin" +) + +type FileCreat struct { + // 表单参数验证结构体支持匿名结构体嵌套 + BaseField + FileInfo +} + +// 验证器语法,参见 Register.go文件,有详细说明 + +func (f FileCreat) CheckParams(context *gin.Context) { + + //1.基本的验证规则没有通过 + if err := context.ShouldBind(&f); err != nil { + response.ValidatorError(context, err) + return + } + + // 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值 + extraAddBindDataContext := data_transfer.DataAddContext(f, consts.ValidatorPrefix, context) + if extraAddBindDataContext == nil { + response.ErrorSystem(context, "fileCreat表单验证器json化失败", "") + } else { + // 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性 + (&web.File{}).Creat(extraAddBindDataContext) + } + +} diff --git a/GinSkeleton/app/http/validator/web/file/Filemove.go b/GinSkeleton/app/http/validator/web/file/Filemove.go new file mode 100644 index 0000000..7b43d7b --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/Filemove.go @@ -0,0 +1,38 @@ +package file + +import ( + "goskeleton/app/global/consts" + "goskeleton/app/http/controller/web" + "goskeleton/app/http/validator/core/data_transfer" + "goskeleton/app/utils/response" + + "github.com/gin-gonic/gin" +) + +type FileMove struct { + // 表单参数验证结构体支持匿名结构体嵌套 + BaseField + FileInfo + Filepath +} + +// 验证器语法,参见 Register.go文件,有详细说明 + +func (f FileMove) CheckParams(context *gin.Context) { + + //1.基本的验证规则没有通过 + if err := context.ShouldBind(&f); err != nil { + response.ValidatorError(context, err) + return + } + + // 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值 + extraAddBindDataContext := data_transfer.DataAddContext(f, consts.ValidatorPrefix, context) + if extraAddBindDataContext == nil { + response.ErrorSystem(context, "FileMove表单验证器json化失败", "") + } else { + // 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性 + (&web.File{}).Move(extraAddBindDataContext) + } + +} diff --git a/GinSkeleton/app/http/validator/web/file/FolderCreat.go b/GinSkeleton/app/http/validator/web/file/FolderCreat.go new file mode 100644 index 0000000..aa129f8 --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/FolderCreat.go @@ -0,0 +1,37 @@ +package file + +import ( + "goskeleton/app/global/consts" + "goskeleton/app/http/controller/web" + "goskeleton/app/http/validator/core/data_transfer" + "goskeleton/app/utils/response" + + "github.com/gin-gonic/gin" +) + +type FolderCreat struct { + // 表单参数验证结构体支持匿名结构体嵌套 + BaseField + Folder +} + +// 验证器语法,参见 Register.go文件,有详细说明 + +func (f FolderCreat) CheckParams(context *gin.Context) { + + //1.基本的验证规则没有通过 + if err := context.ShouldBind(&f); err != nil { + response.ValidatorError(context, err) + return + } + + // 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值 + extraAddBindDataContext := data_transfer.DataAddContext(f, consts.ValidatorPrefix, context) + if extraAddBindDataContext == nil { + response.ErrorSystem(context, "folderCreat表单验证器json化失败", "") + } else { + // 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性 + (&web.File{}).FolderCreat(extraAddBindDataContext) + } + +} diff --git a/GinSkeleton/app/http/validator/web/file/data_type.go b/GinSkeleton/app/http/validator/web/file/data_type.go new file mode 100644 index 0000000..73f86f6 --- /dev/null +++ b/GinSkeleton/app/http/validator/web/file/data_type.go @@ -0,0 +1,31 @@ +package file + +type BaseField struct { + UserName string `form:"user_name" json:"user_name" binding:"required,min=3"` // 必填、对于文本,表示它的长度>=1 + +} + +type FileInfo struct { + FileName string `form:"file_name" json:"file_name" binding:"required"` // 文件名必填 + Path string `form:"file_path" json:"file_path" binding:"required"` // 文件路径必填 +} + +type Folder struct { + FoldereName string `form:"folder_name" json:"folder_name" binding:"required"` // 文件夹名必填 + FolderPath string `form:"folder_path" json:"folder_path" binding:"required"` // 文件夹路径必填 +} + +type Filename struct { + //O_FileName string `form:"oldname" json:"oldname" binding:"required"` // 旧文件名 + N_FileName string `form:"newname" json:"newname" binding:"required"` // 新文件名 +} + +type Filepath struct { + //O_FilePath string `form:"oldpath" json:"oldpath" binding:"required"` // 旧文件路径 + N_FilePath string `form:"newpath" json:"newpath" binding:"required"` // 新文件路径 +} + +type FileUpload struct { + FileName string `form:"file_name" json:"file_name" binding:"required"` // 文件名必填 + SavePath string `form:"save_path" json:"save_path" binding:"required"` // 保存路径必填 +} diff --git a/GinSkeleton/app/service/file/file_cz.go b/GinSkeleton/app/service/file/file_cz.go new file mode 100644 index 0000000..f230517 --- /dev/null +++ b/GinSkeleton/app/service/file/file_cz.go @@ -0,0 +1,35 @@ +package file + +import ( + "os" + "path/filepath" +) + +func CreateFile(userName, filePath string) error { + + // 获取main.go所在的目录 + currentDir, err := os.Getwd() + if err != nil { + return err + } + + baseDir := filepath.Join(currentDir, "file_library") + + userDir := filepath.Join(baseDir, userName) + + // 检查userName对应的文件夹是否存在,如果不存在则创建 + err = os.MkdirAll(userDir, 0755) + if err != nil { + return err + } + + fullFilePath := filepath.Join(baseDir, userName, filePath) + + file, err := os.Create(fullFilePath) + if err != nil { + return err + } + defer file.Close() + + return nil +} diff --git a/GinSkeleton/app/service/file/file_de.go b/GinSkeleton/app/service/file/file_de.go new file mode 100644 index 0000000..79100ee --- /dev/null +++ b/GinSkeleton/app/service/file/file_de.go @@ -0,0 +1,32 @@ +package file + +import ( + "os" + "path/filepath" +) + +func FileDe(userName, filePath string) error { + currentDir, err := os.Getwd() + if err != nil { + return err + } + + baseDir := filepath.Join(currentDir, "file_library") + fullFilePath := filepath.Join(baseDir, userName, filePath) + + // 判断文件是否存在 + _, err = os.Stat(fullFilePath) + if err != nil { + if os.IsNotExist(err) { + return os.ErrNotExist + } + return err + } + + err = os.Remove(fullFilePath) + if err != nil { + return err + } + + return nil +} diff --git a/GinSkeleton/app/service/file/file_get.go b/GinSkeleton/app/service/file/file_get.go new file mode 100644 index 0000000..42daa9a --- /dev/null +++ b/GinSkeleton/app/service/file/file_get.go @@ -0,0 +1,26 @@ +package file + +import ( + "os" + "path/filepath" +) + +func GetFile(userName, filePath string) (*os.File, error) { + + // 获取main.go所在的目录 + currentDir, err := os.Getwd() + if err != nil { + return nil, err + } + + baseDir := filepath.Join(currentDir, "file_library") + + fullFilePath := filepath.Join(baseDir, userName, filePath) + + file, err := os.Open(fullFilePath) + if err != nil { + return nil, err + } + + return file, nil +} diff --git a/GinSkeleton/app/service/file/file_move.go b/GinSkeleton/app/service/file/file_move.go new file mode 100644 index 0000000..44d5549 --- /dev/null +++ b/GinSkeleton/app/service/file/file_move.go @@ -0,0 +1,40 @@ +package file + +import ( + "os" + "path/filepath" +) + +func FileMove(userName, O_FilePath, N_FilePath string) error { + // 获取main.go所在的目录 + currentDir, err := os.Getwd() + if err != nil { + return err + } + + baseDir := filepath.Join(currentDir, "file_library") + + oldFullFilePath := filepath.Join(baseDir, userName, O_FilePath) + newFullFilePath := filepath.Join(baseDir, userName, N_FilePath) + + // 先判断源文件是否存在 + _, err = os.Stat(oldFullFilePath) + if err != nil { + return err + } + + // 判断目标文件路径的上级目录是否存在,如果不存在则创建(确保目标路径合法) + targetDir := filepath.Dir(newFullFilePath) + err = os.MkdirAll(targetDir, 0755) + if err != nil { + return err + } + + // 使用os.Rename进行文件移动操作 + err = os.Rename(oldFullFilePath, newFullFilePath) + if err != nil { + return err + } + + return nil +} diff --git a/GinSkeleton/app/service/file/file_rename.go b/GinSkeleton/app/service/file/file_rename.go new file mode 100644 index 0000000..6b669ea --- /dev/null +++ b/GinSkeleton/app/service/file/file_rename.go @@ -0,0 +1,28 @@ +package file + +import ( + "os" + "path/filepath" +) + +func FileRename(userName, filePath, newFilePath string) error { + + // 获取main.go所在的目录 + currentDir, err := os.Getwd() + if err != nil { + return err + } + + baseDir := filepath.Join(currentDir, "file_library") + + oldfullFilePath := filepath.Join(baseDir, userName, filePath) + + newfullFilePath := filepath.Join(baseDir, userName, newFilePath) + + err = os.Rename(oldfullFilePath, newfullFilePath) + if err != nil { + return err + } + + return nil +} diff --git a/GinSkeleton/app/service/file/file_upload.go b/GinSkeleton/app/service/file/file_upload.go new file mode 100644 index 0000000..902bdb2 --- /dev/null +++ b/GinSkeleton/app/service/file/file_upload.go @@ -0,0 +1,39 @@ +package file + +import ( + "encoding/base64" + "os" + "path/filepath" +) + +func FileSave(userName, savePath, fileDataBase64 string) error { + // 获取main.go所在的目录 + currentDir, err := os.Getwd() + if err != nil { + return err + } + + baseDir := filepath.Join(currentDir, "file_library") + fullFilePath := filepath.Join(baseDir, userName, savePath) + + // 对 base64 编码的文件数据进行解码 base64.StdEncoding.DecodeString() + fileData, err := base64.StdEncoding.DecodeString(fileDataBase64) + if err != nil { + return err + } + + // 创建目标文件,用于写入解码后的文件内容 + targetFile, err := os.Create(fullFilePath) + if err != nil { + return err + } + defer targetFile.Close() + + // 将解码后的文件内容写入到目标文件中 + _, err = targetFile.Write(fileData) + if err != nil { + return err + } + + return nil +} diff --git a/GinSkeleton/app/service/file/folder_creat.go b/GinSkeleton/app/service/file/folder_creat.go new file mode 100644 index 0000000..f71ef17 --- /dev/null +++ b/GinSkeleton/app/service/file/folder_creat.go @@ -0,0 +1,26 @@ +package file + +import ( + "os" + "path/filepath" +) + +func CreateFolder(userName, folderPath string) error { + + // 获取main.go所在的目录 + currentDir, err := os.Getwd() + if err != nil { + return err + } + + baseDir := filepath.Join(currentDir, "file_library") + + fullFolderPath := filepath.Join(baseDir, userName, folderPath) + + err = os.MkdirAll(fullFolderPath, 0755) + if err != nil { + return err + } + + return nil +} diff --git a/GinSkeleton/file_library/111/222/123.docx b/GinSkeleton/file_library/111/222/123.docx new file mode 100644 index 0000000..e69de29 diff --git a/GinSkeleton/file_library/111/test.docx b/GinSkeleton/file_library/111/test.docx new file mode 100644 index 0000000..956431e --- /dev/null +++ b/GinSkeleton/file_library/111/test.docx @@ -0,0 +1 @@ +基于大小模型协同的在线编辑器 \ No newline at end of file diff --git a/GinSkeleton/routers/web.go b/GinSkeleton/routers/web.go index df2d480..7c2b2bc 100644 --- a/GinSkeleton/routers/web.go +++ b/GinSkeleton/routers/web.go @@ -107,6 +107,29 @@ func InitWebRouter_Co() *gin.Engine { users.POST("logout", validatorFactory.Create(consts.ValidatorPrefix+"UsersLogout")) } } + //【需要token】中间件验证的路由 + backend.Use(authorization.CheckTokenAuth()) + { + // 文件操作相关路由组 + file := backend.Group("file/") + { + //创建文件 + file.POST("file_creat", validatorFactory.Create(consts.ValidatorPrefix+"FileCreat")) + //打开文件 + file.GET("file_get", validatorFactory.Create(consts.ValidatorPrefix+"FileGet")) + //文件重命名 + file.POST("file_rename", validatorFactory.Create(consts.ValidatorPrefix+"FileRename")) + //移动文件 + file.POST("file_move", validatorFactory.Create(consts.ValidatorPrefix+"FileMove")) + //保存文件 + file.POST("file_save", validatorFactory.Create(consts.ValidatorPrefix+"FileSave")) + //删除文件 + file.POST("file_delete", validatorFactory.Create(consts.ValidatorPrefix+"FileDelete")) + //创建文件夹 + file.POST("folder_creat", validatorFactory.Create(consts.ValidatorPrefix+"FolderCreat")) + } + } + } return router }