| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- package controllers
- import (
- "Cold_Api/conf"
- "Cold_Api/controllers/lib"
- "Cold_Api/models/Account"
- "Cold_Api/models/FileManager"
- "encoding/json"
- "fmt"
- "math"
- "path/filepath"
- "strings"
- "github.com/beego/beego/v2/adapter/orm"
- beego "github.com/beego/beego/v2/server/web"
- )
- type FileManagerController struct {
- beego.Controller
- Admin_r Account.Admin // 登陆的用户
- T_pid int // 公司id
- }
- func (c *FileManagerController) Prepare() {
- GetCookie := c.Ctx.GetCookie("User_tokey")
- GetString := c.GetString("User_tokey")
- User_tokey := GetString
- if len(User_tokey) == 0 {
- User_tokey = GetCookie
- }
- if Account.Admin_r == nil {
- return
- }
- c.Admin_r = *Account.Admin_r
- T_pid := c.T_pid
- EntryPid, _ := Account.Redis_Tokey_T_pid_Get(User_tokey)
- if EntryPid > 0 {
- T_pid = EntryPid
- }
- c.T_pid = T_pid
- }
- // AddFileManager 添加文件记录(使用form-data格式)
- func (c *FileManagerController) AddFileManager() {
- // 获取form-data参数
- filesParam := c.GetString("files")
- overwriteParam := c.GetString("overwrite")
- pathParam := c.GetString("path")
- // 定义文件信息结构体
- type FileInfo struct {
- Name string `json:"name"` // 文件名
- Url string `json:"url"` // 文件URL
- Size int64 `json:"size"` // 文件大小
- }
- // 参数验证
- if len(filesParam) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "文件参数不能为空"}
- c.ServeJSON()
- return
- }
- // 解析文件列表JSON
- var files []FileInfo
- err := json.Unmarshal([]byte(filesParam), &files)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "文件参数格式错误"}
- c.ServeJSON()
- return
- }
- // 验证文件列表
- if len(files) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "文件列表不能为空"}
- c.ServeJSON()
- return
- }
- // 解析覆盖参数
- overwrite := false
- if overwriteParam == "true" || overwriteParam == "1" {
- overwrite = true
- }
- // 验证每个文件的参数
- var totalSize int64
- for i, file := range files {
- if len(file.Name) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("第%d个文件名不能为空", i+1)}
- c.ServeJSON()
- return
- }
- if len(file.Url) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("第%d个文件链接不能为空", i+1)}
- c.ServeJSON()
- return
- }
- if file.Size <= 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("第%d个文件大小必须大于0", i+1)}
- c.ServeJSON()
- return
- }
- totalSize += file.Size
- }
- // 检查公司存储空间是否足够
- if c.T_pid > 0 {
- available, usedStorage, storageLimit, err := FileManager.Check_Company_Storage_Available(c.T_pid, totalSize)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("检查存储空间失败: %v", err)}
- c.ServeJSON()
- return
- }
- if !available {
- c.Data["json"] = lib.JSONS{
- Code: 202,
- Msg: fmt.Sprintf("存储空间不足,已使用: %s,限制: %s,当前批量文件: %s",
- FileManager.FormatFileSize(usedStorage),
- FileManager.FormatFileSize(storageLimit),
- FileManager.FormatFileSize(totalSize)),
- }
- c.ServeJSON()
- return
- }
- }
- // 处理上传路径
- T_path := pathParam
- if len(T_path) == 0 {
- T_path = "/"
- }
- if !strings.HasSuffix(T_path, "/") {
- T_path += "/"
- }
- // 自动创建路径中不存在的文件夹
- if T_path != "/" {
- err := FileManager.Auto_Create_Folders(c.T_pid, T_path, c.Admin_r.T_uuid)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("创建路径失败: %v", err)}
- c.ServeJSON()
- return
- }
- }
- // 批量处理文件
- var successFiles []FileManager.FileManager_R
- var failedFiles []map[string]interface{}
- var successCount int
- for _, fileInfo := range files {
- // 构建完整路径
- fullPath := T_path + fileInfo.Name
- // 检查是否存在同名文件
- if !overwrite && FileManager.Check_FileManager_Name_Exists(c.T_pid, T_path, fileInfo.Name, 0) {
- failedFiles = append(failedFiles, map[string]interface{}{
- "name": fileInfo.Name,
- "reason": "文件已存在",
- })
- continue
- }
- // 如果覆盖模式,先删除旧文件
- if overwrite {
- o := orm.NewOrm()
- var existingFile FileManager.FileManager
- err := o.QueryTable(new(FileManager.FileManager)).Filter("T_pid", c.T_pid).Filter("T_path", fullPath).Filter("T_state", 1).One(&existingFile)
- if err == nil {
- FileManager.Delete_FileManager_ByUuid(existingFile.T_uuid)
- }
- }
- // 保存文件信息到数据库
- fileManager := FileManager.FileManager{
- T_pid: c.T_pid,
- T_name: fileInfo.Name,
- T_path: fullPath,
- T_url: fileInfo.Url,
- T_size: fileInfo.Size,
- T_type: FileManager.GenerateFileType(fileInfo.Name, fullPath), // 生成文件类型
- T_uploaded_by: c.Admin_r.T_uuid,
- T_state: 1,
- }
- id, err := FileManager.Add_FileManager(fileManager)
- if err != nil {
- failedFiles = append(failedFiles, map[string]interface{}{
- "name": fileInfo.Name,
- "reason": fmt.Sprintf("保存失败: %v", err),
- })
- continue
- }
- fileManager.Id = int(id)
- uploadedFile := FileManager.FileManagerToFileManager_R(fileManager)
- successFiles = append(successFiles, uploadedFile)
- successCount++
- }
- // 构建返回结果
- response := map[string]interface{}{
- "success_count": successCount,
- "failed_count": len(failedFiles),
- "total_count": len(files),
- "success_files": successFiles,
- "failed_files": failedFiles,
- }
- // 根据结果返回不同的消息
- if len(failedFiles) == 0 {
- c.Data["json"] = lib.JSONS{Code: 200, Msg: fmt.Sprintf("所有文件添加成功,共%d个文件", successCount), Data: response}
- } else if successCount == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "所有文件添加失败", Data: response}
- } else {
- c.Data["json"] = lib.JSONS{Code: 200, Msg: fmt.Sprintf("部分文件添加成功,成功%d个,失败%d个", successCount, len(failedFiles)), Data: response}
- }
- c.ServeJSON()
- return
- }
- // DeleteFileManager 删除文件(支持递归删除文件夹及其子文件)
- func (c *FileManagerController) DeleteFileManager() {
- T_path := c.GetString("path")
- if len(T_path) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "文件路径不能为空"}
- c.ServeJSON()
- return
- }
- // 使用递归删除方法(基于路径)
- deletedCount, err := FileManager.Delete_FileManager_Recursive_ByPath(c.T_pid, T_path)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("删除失败: %v", err)}
- c.ServeJSON()
- return
- }
- // 根据删除数量返回不同的成功消息
- var msg string
- if deletedCount > 1 {
- msg = fmt.Sprintf("删除成功,共删除 %d 个文件/文件夹", deletedCount)
- } else {
- msg = "删除成功"
- }
- c.Data["json"] = lib.JSONS{Code: 200, Msg: msg, Data: map[string]interface{}{"deletedCount": deletedCount}}
- c.ServeJSON()
- return
- }
- // CheckFileExists 检查文件列表是否存在
- func (c *FileManagerController) CheckFileExists() {
- // 获取路径列表参数
- pathsParam := c.GetString("paths")
- if len(pathsParam) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "路径列表参数不能为空"}
- c.ServeJSON()
- return
- }
- // 解析路径列表(支持JSON数组格式)
- var paths []string
- if err := json.Unmarshal([]byte(pathsParam), &paths); err != nil {
- // 如果不是JSON格式,按逗号分割
- paths = strings.Split(pathsParam, ",")
- }
- // 存储已存在的路径信息
- var existingFiles []map[string]interface{}
- // 检查每个路径
- for _, path := range paths {
- path = strings.TrimSpace(path)
- if len(path) == 0 {
- continue
- }
- // 检查路径是否存在
- if exists := FileManager.Check_FileManager_Exists_ByPath(c.T_pid, path); exists {
- // 获取文件详细信息
- if file, err := FileManager.Read_FileManager_ByPath(c.T_pid, path); err == nil {
- // 构建返回格式
- fileInfo := map[string]interface{}{
- "name": file.T_name,
- "path": file.T_path,
- "size": file.T_size, // 使用实际文件大小
- "modTime": file.CreateTime.Format("2006-01-02 15:04:05"),
- "isDir": strings.HasSuffix(file.T_path, "/"),
- }
- existingFiles = append(existingFiles, fileInfo)
- }
- }
- }
- // 返回已存在的文件列表
- c.Data["json"] = lib.JSONS{Code: 200, Msg: "success", Data: existingFiles}
- c.ServeJSON()
- return
- }
- // GetFileManagerList 获取文件列表
- func (c *FileManagerController) GetFileManagerList() {
- page, _ := c.GetInt("page")
- if page < 1 {
- page = 1
- }
- page_z, _ := c.GetInt("page_z")
- if page_z < 1 || page_z > 1000 {
- page_z = conf.Page_size
- }
- // 获取查询参数
- path := c.GetString("path", "/")
- search := c.GetString("search", "") // 搜索关键词
- sortBy := c.GetString("sortBy", "name") // 排序字段
- sortOrder := c.GetString("sortOrder", "ascending") // 排序方向
- // 使用简化版查询方法(只查询当前路径直接子项)
- files, total := FileManager.Read_FileManager_List_Simple(
- c.T_pid,
- path,
- search,
- sortBy,
- sortOrder,
- page,
- page_z,
- )
- // 计算分页信息
- totalPages := int(math.Ceil(float64(total) / float64(page_z)))
- // 构建响应数据
- response := map[string]interface{}{
- "Data": files,
- "Num": total,
- "page": page,
- "Page_size": page_z,
- "totalPages": totalPages,
- "path": path,
- "sortBy": sortBy,
- "sortOrder": sortOrder,
- "breadcrumb": FileManager.Get_FileManager_Breadcrumb(path),
- }
- c.Data["json"] = lib.JSONS{Code: 200, Msg: "success", Data: response}
- c.ServeJSON()
- return
- }
- // ------------ 文件夹相关接口 ------------
- // AddFolder 创建文件夹
- func (c *FileManagerController) AddFolder() {
- T_name := c.GetString("T_name")
- if len(T_name) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "文件夹名称不能为空"}
- c.ServeJSON()
- return
- }
- T_path := c.GetString("path", "/")
- if !strings.HasSuffix(T_path, "/") {
- T_path += "/"
- }
- // 自动创建父级路径中不存在的文件夹
- if T_path != "/" {
- err := FileManager.Auto_Create_Folders(c.T_pid, T_path, c.Admin_r.T_uuid)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("创建父级路径失败: %v", err)}
- c.ServeJSON()
- return
- }
- }
- // 检查同级目录下是否存在同名文件夹
- if FileManager.Check_FileManager_Name_Exists(c.T_pid, T_path, T_name, 0) {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "该目录下已存在同名文件夹"}
- c.ServeJSON()
- return
- }
- // 构建文件夹完整路径
- folderPath := T_path + T_name + "/"
- // 创建文件夹
- id, err := FileManager.Add_FileManager_Folder(c.T_pid, T_name, folderPath, c.Admin_r.T_uuid)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "创建文件夹失败"}
- c.ServeJSON()
- return
- }
- c.Data["json"] = lib.JSONS{Code: 200, Msg: "创建成功", Data: map[string]interface{}{"id": id, "path": folderPath}}
- c.ServeJSON()
- return
- }
- // GetBreadcrumb 获取路径面包屑
- func (c *FileManagerController) GetBreadcrumb() {
- T_path := c.GetString("path", "/")
- breadcrumb := FileManager.Get_FileManager_Breadcrumb(T_path)
- c.Data["json"] = lib.JSONS{Code: 200, Msg: "success", Data: breadcrumb}
- c.ServeJSON()
- return
- }
- // RenameFile 重命名文件或文件夹
- func (c *FileManagerController) RenameFile() {
- // 支持两种参数格式:
- // 1. 传统的id + T_name格式
- // 2. 新的oldName + newName格式(参考API)
- oldName := c.GetString("oldName")
- newName := c.GetString("newName")
- path := c.GetString("path")
- // 如果使用新格式
- if len(oldName) > 0 && len(newName) > 0 {
- c.renameByPath(oldName, newName, path)
- return
- }
- }
- // renameByPath 基于路径的重命名方法
- func (c *FileManagerController) renameByPath(oldPath, newPath, parentPath string) {
- // 参数验证
- if len(oldPath) == 0 || len(newPath) == 0 {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "路径参数不能为空"}
- c.ServeJSON()
- return
- }
- // 从完整路径中提取文件名
- newName := filepath.Base(newPath)
- // 确保路径以/开头
- if !strings.HasPrefix(oldPath, "/") {
- oldPath = "/" + oldPath
- }
- if !strings.HasPrefix(newPath, "/") {
- newPath = "/" + newPath
- }
- // 查找要重命名的文件/文件夹
- file, err := FileManager.Read_FileManager_ByPath(c.T_pid, oldPath)
- if err != nil {
- // 如果是文件夹,尝试添加/后缀
- if !strings.HasSuffix(oldPath, "/") {
- file, err = FileManager.Read_FileManager_ByPath(c.T_pid, oldPath+"/")
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "文件或文件夹不存在"}
- c.ServeJSON()
- return
- }
- oldPath += "/"
- newPath += "/"
- } else {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "文件或文件夹不存在"}
- c.ServeJSON()
- return
- }
- }
- // 验证权限
- if file.T_pid != c.T_pid {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "权限不足"}
- c.ServeJSON()
- return
- }
- // 检查新路径是否已存在
- exists := FileManager.Check_FileManager_Exists_ByPath(c.T_pid, newPath)
- if exists {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "目标路径已存在"}
- c.ServeJSON()
- return
- }
- // 执行重命名
- if strings.HasSuffix(oldPath, "/") { // 文件夹
- err = FileManager.Update_Folder_And_Children_Path(c.T_pid, oldPath, newPath, newName)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("重命名文件夹失败: %v", err)}
- c.ServeJSON()
- return
- }
- } else { // 文件
- file.T_name = newName
- file.T_path = newPath
- success := FileManager.Update_FileManager(file, "T_name", "T_path", "UpdateTime")
- if !success {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: "重命名失败"}
- c.ServeJSON()
- return
- }
- }
- c.Data["json"] = lib.JSONS{Code: 200, Msg: "重命名成功"}
- c.ServeJSON()
- return
- }
- // GetStorageInfo 获取公司存储使用情况
- func (c *FileManagerController) GetStorageInfo() {
- // 获取存储信息
- storageInfo, err := FileManager.Get_Company_Storage_Info(c.T_pid)
- if err != nil {
- c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("获取存储信息失败: %v", err)}
- c.ServeJSON()
- return
- }
- c.Data["json"] = lib.JSONS{Code: 200, Msg: "success", Data: storageInfo}
- c.ServeJSON()
- return
- }
- // GetUploadToken 获取七牛云上传Token
- func (c *FileManagerController) GetUploadToken() {
- // 获取文件后缀参数
- fileSuffix := c.GetString("suffix", "")
- // 生成上传Token
- uploadToken := lib.UploadToken(fileSuffix)
- c.Data["json"] = lib.JSONS{
- Code: 200,
- Msg: "success",
- Data: map[string]interface{}{
- "token": uploadToken,
- "domain": "", // 七牛云访问域名(如需要可从配置获取)
- },
- }
- c.ServeJSON()
- return
- }
|