diff --git a/dao/file.go b/dao/file.go new file mode 100644 index 0000000..f2843fd --- /dev/null +++ b/dao/file.go @@ -0,0 +1,61 @@ +package dao + +import "gorm.io/gorm" + +type File struct { + gorm.Model + // 存储文件名 + FileStoreName string `gorm:"column:file_store_name;uniqueIndex:idx_file_name"` + FileName string `gorm:"column:file_name"` + FileSize int `gorm:"column:file_size"` + FileType string `gorm:"column:file_type"` + FilePath string `gorm:"column:file_path"` + AuthID int `gorm:"column:auth_id"` +} + +func CreateFile(fileStoreName, fileName, fileType, filePath string, fileSize, authID int) uint { + file := File{FileStoreName: fileStoreName, FileName: fileName, FileType: fileType, FilePath: filePath, FileSize: fileSize, AuthID: authID} + result := DB.Debug().Create(&file) + if result.Error != nil { + return 0 + } + return file.ID +} + +func DeleteFileByID(id, user int) bool { + res := DB.Debug().Model(&File{}).Where("id = ? and auth_id = ?", id, user).Delete(&File{}) + if res.Error != nil { + return false + } + return true +} + +func FindFileByID(id, auth_id int) File { + var file File + DB.Debug().Where("id = ? and auth_id = ?", id, auth_id).First(&file) + return file +} + +func FindFileByNames(fileName string, auth_id int) File { + var file File + DB.Debug().Where("file_name = ? and auth_id = ?", fileName, auth_id).First(&file) + return file +} + +func FindFileByAuthID(auth_id int) []File { + var files []File + DB.Debug().Where("auth_id = ?", auth_id).Find(&files) + return files +} + +func UpdateFileByID(id, auth_id int, fileStoreName, fileName, fileType, filePath string, fileSize int) bool { + pd := FindFileByID(id, auth_id) + if pd.ID == 0 { + return false + } + result := DB.Debug().Model(&File{}).Where("id = ? and auth_id = ?", id, auth_id).Updates(File{FileStoreName: fileStoreName, FileName: fileName, FileType: fileType, FilePath: filePath, FileSize: fileSize}) + if result.Error != nil { + return false + } + return true +} diff --git a/dao/user.go b/dao/user.go index b36d550..d7aae5f 100644 --- a/dao/user.go +++ b/dao/user.go @@ -16,6 +16,7 @@ type User struct { Role string `gorm:"column:role"` Redis bool `gorm:"column:redis"` Run bool `gorm:"column:run"` + Upload bool `gorm:"column:upload"` CreateTime string `gorm:"column:create_time"` UpdateTime string `gorm:"column:update_time"` } diff --git a/handler/tool.go b/handler/tool.go index e566e76..f9c593d 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -19,6 +19,66 @@ func SetUpToolGroup(router *gin.Engine) { toolGroup := router.Group("/tool") toolGroup.POST("/set_redis", SetRedis) toolGroup.POST("/get_redis", GetRedis) + + //文件上传、下载 + toolGroup.POST("/upload", UploadFile) + toolGroup.GET("/download/:filename", DownloadFile) +} + +func UploadFile(c *gin.Context) { + //先查看是否有权限 + id, _ := c.Get("id") + id1 := int(id.(float64)) + //从请求头获取upload_type + uploadType := c.GetHeader("upload_type") + if uploadType == "" { + c.JSON(http.StatusOK, gin.H{"error": "upload_type is empty", "code": proto.ParameterError, "message": "failed"}) + return + } + + user := dao.FindUserByUserID(id1) + if user.Upload == false { + c.JSON(http.StatusOK, gin.H{"error": "no upload Permissions", "code": proto.NoUploadPermissions, "message": "failed"}) + return + } + //上传文件 + file, err := c.FormFile("file") + if err != nil { + c.JSON(http.StatusOK, gin.H{"error": "upload file failed", "code": proto.UploadFileFailed, "message": "failed"}) + return + } + + //保存文件 + filePath, fileStoreName, err := service.SaveFile(file, uploadType) + if err != nil { + c.JSON(http.StatusOK, gin.H{"error": "save file failed", "code": proto.SaveFileFailed, "message": "failed"}) + return + } + //保存文件信息 + fileSize := int(file.Size) + fileName := file.Filename + fileType := file.Header.Get("file_type") + fileID := dao.CreateFile(fileStoreName, fileName, fileType, filePath, fileSize, id1) + if fileID == 0 { + c.JSON(http.StatusOK, gin.H{"error": "save file info failed", "code": proto.SaveFileInfoFailed, "message": "failed"}) + return + } + +} + +func DownloadFile(c *gin.Context) { + //参数 + filename := c.Param("filename") + //file_id, _ := strconv.Atoi(c.Query("id")) + id, _ := c.Get("id") + //查询文件信息 + file := dao.FindFileByNames(filename, int(id.(float64))) + if file.ID == 0 { + c.JSON(http.StatusOK, gin.H{"error": "file not found", "code": proto.FileNotFound, "message": "failed"}) + return + } + //下载文件 + c.File(file.FilePath + file.FileStoreName) } func SetRedis(c *gin.Context) { diff --git a/proto/conf.go b/proto/conf.go index af1a95b..ec3a8ff 100644 --- a/proto/conf.go +++ b/proto/conf.go @@ -18,6 +18,9 @@ const ( // 以下是持续集成、部署的配置 CID_BASE_DIR = "/home/lijun/cid/" + + // 以下是文件上传的配置 + FILE_BASE_DIR = "/home/lijun/file/" ) const ( @@ -34,6 +37,13 @@ const ( MSG_STATUS_UNREAD = 0 // 未读 ) +const ( + //文件上传类型 + File_TYPE = 1 // 通用文件 + //用于视频解析 + Video_TYPE = 2 // 视频文件 +) + type User struct { gorm.Model Name string `gorm:"column:name"` diff --git a/proto/status.go b/proto/status.go index a0f71cb..2677aa4 100644 --- a/proto/status.go +++ b/proto/status.go @@ -49,4 +49,12 @@ const ( //消息错误码 MsgSendFailed = 61 // 消息发送失败 + + //文件错误码 + FileNotFound = 71 // 文件不存在 + FileUploadFailed = 72 // 文件上传失败 + SaveFileInfoFailed = 73 // 保存文件信息失败 + SaveFileFailed = 74 // 保存文件失败 + UploadFileFailed = 75 // 上传文件失败 + NoUploadPermissions = 76 // 无上传权限 ) diff --git a/service/fileService.go b/service/fileService.go new file mode 100644 index 0000000..b5de17a --- /dev/null +++ b/service/fileService.go @@ -0,0 +1,60 @@ +package service + +import ( + "github.com/google/uuid" + "io" + "mime/multipart" + "os" + "path" + "time" + "videoplayer/proto" + "videoplayer/worker" +) + +// 检查path是否存在当前日期文件夹如(2024-08-09),不存在则path下当前日期文件夹创建,存在则返回 +func getFilePath(path string) string { + //当前日期,格式为2024-08-09 + date := time.Now().Format("2006-01-02") + //拼接文件路径 + filePath := path + "/" + date + //判断文件夹是否存在 + _, err := os.Stat(filePath) + if err != nil { + //不存在则创建 + os.MkdirAll(filePath, os.ModePerm) + } + return filePath +} + +func SaveFile(file *multipart.FileHeader, uploadType string) (string, string, error) { + //获取文件后缀 + fileSuffix := path.Ext(file.Filename) + //生成文件名 + fileStoreName := uuid.NewString() + fileSuffix + //生成文件路径 + path_ := getFilePath(proto.FILE_BASE_DIR) + filePath := path_ + "/" + fileStoreName + + //保存文件file + dst, err := os.Create(filePath) + if err != nil { + return "", "", err + } + defer dst.Close() + + // 复制文件内容 + file_, err := file.Open() + if err != nil { + return "", "", err + } + _, err = io.Copy(dst, file_) + if err != nil { + return "", "", err + } + + if uploadType == "2" { + worker.PushRedisList("video_need_handle", filePath) + } + + return path_, fileStoreName, nil +}