583 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			583 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package controllers
 | ||
| 
 | ||
| import (
 | ||
| 	"encoding/json"
 | ||
| 	"os"
 | ||
| 	"path"
 | ||
| 	"path/filepath"
 | ||
| 	"server/models"
 | ||
| 	"strconv"
 | ||
| 	"strings"
 | ||
| 	"time"
 | ||
| 
 | ||
| 	beego "github.com/beego/beego/v2/server/web"
 | ||
| )
 | ||
| 
 | ||
| // FileController 处理文件相关请求
 | ||
| type FileController struct {
 | ||
| 	beego.Controller
 | ||
| }
 | ||
| 
 | ||
| // GetAllFiles 获取所有文件信息
 | ||
| func (c *FileController) GetAllFiles() {
 | ||
| 	files, err := models.GetAllFiles()
 | ||
| 
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取文件列表失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取文件列表成功",
 | ||
| 			"data":    files,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // GetFileById 根据ID获取文件信息
 | ||
| func (c *FileController) GetFileById() {
 | ||
| 	idStr := c.Ctx.Input.Param(":id")
 | ||
| 	id, err := strconv.ParseInt(idStr, 10, 64)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "参数错误",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	file, err := models.GetFileById(id)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "文件不存在",
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取文件成功",
 | ||
| 			"data":    file,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // GetFilesByTenant 根据租户ID获取文件信息
 | ||
| func (c *FileController) GetFilesByTenant() {
 | ||
| 	tenantID := c.GetString("tenant_id")
 | ||
| 	if tenantID == "" {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "租户ID不能为空",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	files, err := models.GetFilesByTenant(tenantID)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取文件列表失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取文件列表成功",
 | ||
| 			"data":    files,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // GetFilesByCategory 根据分类获取文件信息
 | ||
| func (c *FileController) GetFilesByCategory() {
 | ||
| 	category := c.GetString("category")
 | ||
| 	if category == "" {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "分类不能为空",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	files, err := models.GetFilesByCategory(category)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取文件列表失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取文件列表成功",
 | ||
| 			"data":    files,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // GetFilesByStatus 根据状态获取文件信息
 | ||
| func (c *FileController) GetFilesByStatus() {
 | ||
| 	statusStr := c.GetString("status")
 | ||
| 	status, err := strconv.Atoi(statusStr)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "状态参数错误",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	files, err := models.GetFilesByStatus(int8(status))
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取文件列表失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取文件列表成功",
 | ||
| 			"data":    files,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // CreateFile 创建新文件信息
 | ||
| func (c *FileController) CreateFile() {
 | ||
| 	var file models.FileInfo
 | ||
| 
 | ||
| 	// 解析请求体
 | ||
| 	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &file); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "请求参数错误",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 从JWT中间件获取用户信息
 | ||
| 	if userID, ok := c.Ctx.Input.GetData("userId").(int); ok && userID > 0 {
 | ||
| 		file.UserID = userID
 | ||
| 	}
 | ||
| 	if username, ok := c.Ctx.Input.GetData("username").(string); ok && username != "" {
 | ||
| 		file.UploadBy = username
 | ||
| 	}
 | ||
| 
 | ||
| 	// 验证必填字段
 | ||
| 	if file.TenantID == "" || file.FileName == "" || file.OriginalName == "" ||
 | ||
| 		file.FilePath == "" || file.FileType == "" || file.FileExt == "" ||
 | ||
| 		file.Category == "" || file.UploadBy == "" {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "必填字段不能为空",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 添加文件信息
 | ||
| 	if _, err := models.AddFile(&file); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "创建文件失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "创建文件成功",
 | ||
| 			"data":    file,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // UpdateFile 更新文件信息
 | ||
| func (c *FileController) UpdateFile() {
 | ||
| 	idStr := c.Ctx.Input.Param(":id")
 | ||
| 	id, err := strconv.ParseInt(idStr, 10, 64)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "参数错误",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	var file models.FileInfo
 | ||
| 	file.ID = id
 | ||
| 
 | ||
| 	// 解析请求体
 | ||
| 	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &file); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "请求参数错误",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 更新文件信息
 | ||
| 	if err := models.UpdateFile(&file); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "更新文件失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "更新文件成功",
 | ||
| 			"data":    file,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // DeleteFile 删除文件信息(软删除)
 | ||
| func (c *FileController) DeleteFile() {
 | ||
| 	idStr := c.Ctx.Input.Param(":id")
 | ||
| 	id, err := strconv.ParseInt(idStr, 10, 64)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "参数错误",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	if err := models.DeleteFile(id); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "删除文件失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "删除文件成功",
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // HardDeleteFile 硬删除文件信息
 | ||
| func (c *FileController) HardDeleteFile() {
 | ||
| 	idStr := c.Ctx.Input.Param(":id")
 | ||
| 	id, err := strconv.ParseInt(idStr, 10, 64)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "参数错误",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	if err := models.HardDeleteFile(id); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "删除文件失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "删除文件成功",
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // GetFileStatistics 获取文件统计信息
 | ||
| func (c *FileController) GetFileStatistics() {
 | ||
| 	tenantID := c.GetString("tenant_id")
 | ||
| 	if tenantID == "" {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "租户ID不能为空",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	stats, err := models.GetFileStatistics(tenantID)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取统计信息失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取统计信息成功",
 | ||
| 			"data":    stats,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // SearchFiles 搜索文件
 | ||
| func (c *FileController) SearchFiles() {
 | ||
| 	keyword := c.GetString("keyword")
 | ||
| 	tenantID := c.GetString("tenant_id")
 | ||
| 
 | ||
| 	if keyword == "" {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "搜索关键词不能为空",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	if tenantID == "" {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "租户ID不能为空",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	files, err := models.SearchFiles(keyword, tenantID)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "搜索文件失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "搜索文件成功",
 | ||
| 			"data":    files,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // GetMyFiles 获取当前用户的文件列表
 | ||
| func (c *FileController) GetMyFiles() {
 | ||
| 	// 从JWT中间件获取用户信息
 | ||
| 	userID, ok := c.Ctx.Input.GetData("userId").(int)
 | ||
| 	if !ok || userID <= 0 {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "用户未登录或登录已过期",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	files, err := models.GetFilesByUserID(userID)
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取文件列表失败: " + err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取成功",
 | ||
| 			"data":    files,
 | ||
| 		}
 | ||
| 	}
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // GetFilesPublic 不需要认证的获取文件信息接口
 | ||
| func (c *FileController) GetFilesPublic() {
 | ||
| 	files, err := models.GetAllFiles()
 | ||
| 
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取文件列表失败",
 | ||
| 			"error":   err.Error(),
 | ||
| 		}
 | ||
| 	} else {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": true,
 | ||
| 			"message": "获取文件列表成功",
 | ||
| 			"data":    files,
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	c.ServeJSON()
 | ||
| }
 | ||
| 
 | ||
| // Post 处理文件上传
 | ||
| func (c *FileController) Post() {
 | ||
| 	// 从JWT中间件获取用户信息
 | ||
| 	userID, ok := c.Ctx.Input.GetData("userId").(int)
 | ||
| 	if !ok || userID <= 0 {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "用户未登录或登录已过期",
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	username, _ := c.Ctx.Input.GetData("username").(string)
 | ||
| 	if username == "" {
 | ||
| 		username = "unknown"
 | ||
| 	}
 | ||
| 
 | ||
| 	// 获取上传的文件
 | ||
| 	file, header, err := c.GetFile("file")
 | ||
| 	if err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "获取上传文件失败: " + err.Error(),
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 	defer file.Close()
 | ||
| 
 | ||
| 	// 获取文件基本信息
 | ||
| 	originalName := header.Filename
 | ||
| 	fileSize := header.Size
 | ||
| 	fileExt := strings.ToLower(filepath.Ext(originalName))
 | ||
| 	fileName := strings.TrimSuffix(originalName, fileExt)
 | ||
| 
 | ||
| 	// 获取分类(可选)
 | ||
| 	category := c.GetString("category")
 | ||
| 	if category == "" {
 | ||
| 		category = "未分类"
 | ||
| 	}
 | ||
| 
 | ||
| 	// 获取租户ID(可选,从请求参数或中间件获取)
 | ||
| 	tenantID := c.GetString("tenant_id")
 | ||
| 	if tenantID == "" {
 | ||
| 		tenantID = "default"
 | ||
| 	}
 | ||
| 
 | ||
| 	// 生成日期路径(年/月/日)
 | ||
| 	now := time.Now()
 | ||
| 	datePath := now.Format("2006/01/02")
 | ||
| 
 | ||
| 	// 目录改成 server 文件夹目录下的 uploads
 | ||
| 	uploadDir := filepath.Join("uploads", datePath)
 | ||
| 
 | ||
| 	// 清理路径
 | ||
| 	uploadDir = filepath.Clean(uploadDir)
 | ||
| 
 | ||
| 	// 确保目录存在
 | ||
| 	if err := os.MkdirAll(uploadDir, 0755); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "创建上传目录失败: " + err.Error(),
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 生成唯一文件名(时间戳 + 原始文件名)
 | ||
| 	timestamp := now.Format("20060102150405")
 | ||
| 	uniqueFileName := timestamp + "_" + originalName
 | ||
| 	savePath := path.Join(uploadDir, uniqueFileName)
 | ||
| 
 | ||
| 	// 计算相对路径(用于存储到数据库)
 | ||
| 	relativePath := path.Join("uploads", datePath, uniqueFileName)
 | ||
| 
 | ||
| 	// 保存文件
 | ||
| 	if err := c.SaveToFile("file", savePath); err != nil {
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "保存文件失败: " + err.Error(),
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 获取文件类型
 | ||
| 	fileType := "other"
 | ||
| 	switch fileExt {
 | ||
| 	case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp":
 | ||
| 		fileType = "image"
 | ||
| 	case ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".txt":
 | ||
| 		fileType = "document"
 | ||
| 	case ".mp4", ".avi", ".mov", ".wmv":
 | ||
| 		fileType = "video"
 | ||
| 	case ".mp3", ".wav", ".flac":
 | ||
| 		fileType = "audio"
 | ||
| 	case ".zip", ".rar", ".7z":
 | ||
| 		fileType = "archive"
 | ||
| 	}
 | ||
| 
 | ||
| 	// 构造文件URL(相对路径)
 | ||
| 	fileURL := "/" + relativePath
 | ||
| 
 | ||
| 	// 创建文件信息记录
 | ||
| 	fileInfo := models.FileInfo{
 | ||
| 		TenantID:     tenantID,
 | ||
| 		UserID:       userID,
 | ||
| 		FileName:     fileName,
 | ||
| 		OriginalName: originalName,
 | ||
| 		FilePath:     relativePath,
 | ||
| 		FileURL:      fileURL,
 | ||
| 		FileSize:     fileSize,
 | ||
| 		FileType:     fileType,
 | ||
| 		FileExt:      fileExt,
 | ||
| 		Category:     category,
 | ||
| 		UploadBy:     username,
 | ||
| 		UploadTime:   now,
 | ||
| 	}
 | ||
| 
 | ||
| 	// 保存到数据库
 | ||
| 	id, err := models.AddFile(&fileInfo)
 | ||
| 	if err != nil {
 | ||
| 		// 如果数据库保存失败,删除已上传的文件
 | ||
| 		os.Remove(savePath)
 | ||
| 		c.Data["json"] = map[string]interface{}{
 | ||
| 			"success": false,
 | ||
| 			"message": "保存文件信息失败: " + err.Error(),
 | ||
| 		}
 | ||
| 		c.ServeJSON()
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	fileInfo.ID = id
 | ||
| 
 | ||
| 	// 返回成功响应
 | ||
| 	c.Data["json"] = map[string]interface{}{
 | ||
| 		"success": true,
 | ||
| 		"message": "文件上传成功",
 | ||
| 		"data":    fileInfo,
 | ||
| 	}
 | ||
| 	c.ServeJSON()
 | ||
| }
 |