saw-go/service/fileService.go

447 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"StuAcaWorksAI/dao"
"StuAcaWorksAI/proto"
"StuAcaWorksAI/worker"
"crypto/md5"
"encoding/base64"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"io"
"log"
"mime/multipart"
"os"
"path"
"regexp"
"strings"
"time"
)
// 检查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(c *gin.Context, 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
//保存文件
if err := c.SaveUploadedFile(file, filePath); err != nil {
return "", "", err
}
if uploadType == "2" {
worker.PushRedisList("video_need_handle", filePath)
}
return path_, fileStoreName, nil
}
func CalculateFileMd5(file io.Reader) string {
hash := md5.New()
if _, err := io.Copy(hash, file); err != nil {
return ""
}
return fmt.Sprintf("%x", hash.Sum(nil))
}
func CheckUploadRequestParameters(req *proto.FileUploadReq) error {
var err error
if req.AuthType == "" {
err = fmt.Errorf("auth_type is empty")
}
if req.UploadType == "" {
req.UploadType = "1"
}
if req.UploadType != "1" {
req.UploadType = "2"
}
if proto.File_Type[req.Type] == 0 {
err = fmt.Errorf("file type is invalid")
}
return err
}
func CreateConfigFile(req *proto.AddConfigFileReq, userId int) error {
var err error
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
err = fmt.Errorf("user not found or no permission")
return err
}
if req.FileName == "" || req.FilePath == "" {
err = fmt.Errorf("file name or file path is empty")
return err
}
//查看系统中是否存在文件,不存在则创建
file := req.FilePath + "/" + req.FileName
//正则判断文件名是否合法
pattern := `^/([^/:\*?]+/)*([^/:\*?]+)?$`
reg := regexp.MustCompile(pattern)
if reg.MatchString(file) == false {
err = fmt.Errorf("file path is invalid")
return err
}
_, fileErr := os.Stat(file)
if fileErr != nil {
//创建文件
f, err2 := os.Create(file)
if err2 != nil {
err = err2
return err
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
fmt.Println("Error closing file")
}
}(f)
}
//创建
configFile := dao.ConfigFile{FilePath: req.FilePath, FileName: req.FileName, AuthID: userId}
_, err3 := dao.CreateConfigFile(configFile)
if err3 != nil {
err = err3
return err
}
return err
}
func DeleteConfigFile(req *proto.ConfigFileReq, userId int) error {
var err error
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
err = fmt.Errorf("user not found or no permission")
return err
}
//删除文件
config_file := dao.FindConfigFileByID(req.ID, userId)
if config_file.ID == 0 {
err = fmt.Errorf("config file not found")
return err
}
err = dao.DeleteConfigFileByID(req.ID)
if req.DelFile {
file := config_file.FilePath + "/" + config_file.FileName
err = os.Remove(file)
if err != nil {
return err
}
}
//删除数据库记录
return err
}
type ConfigFileService struct {
}
func (c *ConfigFileService) UpdateConfigFile(req *proto.ConfigFileReq, userId int) error {
var err error
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
err = fmt.Errorf("user not found or no permission")
return err
}
config_file := dao.FindConfigFileByID(req.ID, userId)
if config_file.ID == 0 {
err = fmt.Errorf("config file not found")
return err
}
//修改文件名
if req.FileName != "" {
file := config_file.FilePath + "/" + config_file.FileName
new_file := config_file.FilePath + "/" + req.FileName
err = os.Rename(file, new_file)
if err != nil {
return err
}
err = dao.UpdateConfigFileByID(req.ID, dao.ConfigFile{FileName: req.FileName})
}
if req.Content != "" {
file := config_file.FilePath + "/" + config_file.FileName
f, err2 := os.OpenFile(file, os.O_WRONLY|os.O_TRUNC, 0644) //打开文件,清空文件内容,写入新内容,不存在则创建
if err2 != nil {
err = err2
return err
}
defer func(f *os.File) {
err3 := f.Close()
if err3 != nil {
fmt.Println("Error closing file")
}
}(f)
_, err = f.WriteString(req.Content)
if err != nil {
return err
}
}
return err
}
func (c *ConfigFileService) SearchOneConfigFile(req *proto.ConfigFileReq, userId int) ([]proto.SearchOneConfigFileResp, error) {
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
return []proto.SearchOneConfigFileResp{}, fmt.Errorf("user not found or no permission")
}
config_file := dao.FindConfigFileByID(req.ID, userId)
if config_file.ID == 0 {
return []proto.SearchOneConfigFileResp{}, fmt.Errorf("config file not found")
}
file := config_file.FilePath + "/" + config_file.FileName
content, err2 := os.ReadFile(file)
if err2 != nil {
return []proto.SearchOneConfigFileResp{}, err2
}
resp := []proto.SearchOneConfigFileResp{{ID: config_file.ID, FilePath: config_file.FilePath, FileName: config_file.FileName, Content: string(content), CreatedAt: config_file.CreatedAt, UpdatedAt: config_file.UpdatedAt}}
return resp, nil
}
func (c *ConfigFileService) SearchAllConfigFile(userId int) ([]dao.ConfigFile, error) {
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
return []dao.ConfigFile{}, fmt.Errorf("user not found or no permission")
}
config_files := dao.FindConfigFileByAuthID(userId)
return config_files, nil
}
func UpdateUserFile(userID int, fileAuthID int, fileAuthName string) error {
fileAuth := dao.FindFileAuthByID(fileAuthID)
if fileAuth.ID == 0 {
return errors.New("file auth not found")
}
if fileAuth.AuthID != userID {
return errors.New("no permission")
}
fileAuth.UserFileName = fileAuthName
err := dao.UpdateFileAuthByID(fileAuthID, fileAuth)
return err
}
func DeleteUserFile(userID, fileAuthID int) error {
fileAuth := dao.FindFileAuthByID(fileAuthID)
if fileAuth.ID == 0 {
return errors.New("file auth not found")
}
if fileAuth.AuthID != userID {
return errors.New("no permission")
}
err := dao.DeleteFileAuthByID(fileAuthID)
return err
}
func CreateUserFile(userID int, fileAuthName string, fileID int, UploadType string) dao.FileAuth {
//先查fileAuthName是否存在
fileAuth := dao.FindFileAuthByName(fileAuthName, userID)
if fileAuth.ID != 0 {
log.Println("file auth name already exist, please change another name: ", fileAuthName)
//将要保存的文件名改为fileAuthName+uuid
strs := strings.Split(fileAuth.UserFileName, ".")
//当前时间戳
timestamp := time.Now().Unix()
timestampStr := fmt.Sprintf("%d", timestamp)
fileAuthName = strs[0] + "_" + timestampStr + "." + strs[1]
//return fileAuth
}
fileAuth_ := dao.CreateFileAuth(userID, fileID, fileAuthName, UploadType, 1, "")
return fileAuth_
}
func FindUserFileList(userID int, uploadType string) []dao.UserFileListResp {
fileList, files := dao.FileUserFileList(userID, uploadType)
filesM := make(map[uint]dao.File)
for _, file := range files {
filesM[file.ID] = file
}
var res []dao.UserFileListResp
for _, file := range fileList {
fileStoreName := filesM[uint(file.FileID)].FileStoreName
r := dao.UserFileListResp{FileAuth: file, FileStoreName: fileStoreName}
res = append(res, r)
}
log.Println("FindUserFileList res:", len(res))
return res
}
func CreateUserFileAfterUnique() {
}
func FindFileContent(userID int, userReq *proto.FileContentReq) ([]dao.FileContent, error) {
fileAuth := dao.FindFileAuthByID(userReq.UserFileID)
if fileAuth.ID == 0 {
return nil, errors.New("file auth not found")
}
if fileAuth.AuthID != userID {
return nil, errors.New("no permission")
}
//获取文件基础信息
file := dao.FindFileByID(fileAuth.FileID, userID)
//判断文件类型\
fileType := strings.Split(file.FileStoreName, ".")[1]
//如果文件类型是图片
if fileType == "jpg" || fileType == "png" || fileType == "jpeg" || fileType == "gif" {
return nil, errors.New("file type is image")
}
//获取文件内容
fileContents := dao.FindFileContentByFileID(fileAuth.FileID)
if len(fileContents) == 0 {
//直接读取文件内容
filePath := file.FilePath + "/" + file.FileStoreName
fileContentStr, err := readFileContent(filePath)
if err != nil {
return nil, err
}
var fileContent dao.FileContent
fileContent.FileID = -1
fileContent.FileContent = fileContentStr
fileContents = append(fileContents, fileContent)
}
return fileContents, nil
}
func CreateFileContent(userID, fileID int, fileContent string) (uint, error) {
user := GetUserByIDWithCache(userID)
if user.Role != "admin" {
return 0, errors.New("no permission")
}
//查找文件是否存在
fileContentC, err := dao.FindFileContentByFileIDAndContentID(fileID)
if err != nil {
return 0, err
}
//如果文件存在,则更新文件内容
if fileContentC.ID != 0 {
return dao.UpdateFileContentByID(fileContentC.ID, fileContent)
}
return dao.CreateFileContent(fileID, fileContent)
}
func GetFileWillConvertContentFileList(userID int) ([]dao.File, error) {
user := GetUserByIDWithCache(userID)
if user.Role != "admin" {
return nil, errors.New("no permission")
}
files, err2 := dao.GetFileWillConvertContentFileList()
if err2 != nil {
return nil, err2
}
var res []dao.File
for _, file := range files {
fileType := strings.Split(file.FileStoreName, ".")[1]
//如果文件类型是图片则不需要返回
if fileType == "jpg" || fileType == "png" || fileType == "jpeg" || fileType == "gif" {
continue
}
//如果文件类型是视频则不需要返回
if fileType == "mp4" || fileType == "avi" || fileType == "rmvb" || fileType == "mkv" {
continue
}
//如果文件类型是音频则不需要返回
if fileType == "mp3" || fileType == "wav" || fileType == "wma" {
continue
}
//如果文件类型是压缩包则不需要返回
if fileType == "zip" || fileType == "rar" || fileType == "7z" {
continue
}
res = append(res, file)
}
return res, nil
}
func readFileContent(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
defer file.Close()
content, err := io.ReadAll(file)
if err != nil {
return "", err
}
return string(content), nil
}
func FindFileContentV2(fileID, userID int) ([]dao.FileContent, error) {
//获取文件基础信息
file := dao.FindFileByID(fileID, userID)
//判断文件类型\
fileType := strings.Split(file.FileStoreName, ".")[1]
//如果文件类型是图片
if fileType == "jpg" || fileType == "png" || fileType == "jpeg" || fileType == "gif" {
return nil, errors.New("file type is image")
}
//获取文件内容
fileContents := dao.FindFileContentByFileID(fileID)
if len(fileContents) == 0 {
//直接读取文件内容
filePath := file.FilePath + "/" + file.FileStoreName
fileContentStr, err := readFileContent(filePath)
if err != nil {
return nil, err
}
var fileContent dao.FileContent
fileContent.FileID = -1
fileContent.FileContent = fileContentStr
fileContents = append(fileContents, fileContent)
}
return fileContents, nil
}
func FindImageFileContent(fileID, userID int) (string, error) {
//获取文件基础信息
file := dao.FindFileByID(fileID, userID)
//判断文件类型\
fileType := strings.Split(file.FileStoreName, ".")[1]
//如果文件类型是图片
if fileType != "jpg" && fileType != "png" && fileType != "jpeg" && fileType != "gif" {
return "", errors.New("file type is not image")
}
//直接读取文件内容
filePath := file.FilePath + "/" + file.FileStoreName
base64Str, err := readImageFile(filePath)
if err != nil {
return "", err
}
return base64Str, nil
}
// readImageFile 函数用于读取指定路径的图片文件并将其内容转换为 Base64 编码字符串
func readImageFile(filePath string) (string, error) {
// 打开图片文件
file, err := os.Open(filePath)
if err != nil {
return "", fmt.Errorf("无法打开文件: %w", err)
}
// 确保文件在函数结束时关闭
defer file.Close()
// 读取图片文件内容
imageData, err := io.ReadAll(file)
if err != nil {
return "", fmt.Errorf("无法读取文件内容: %w", err)
}
// 将图片数据进行 Base64 编码
base64Encoded := base64.StdEncoding.EncodeToString(imageData)
return base64Encoded, nil
}