From 46ad8baa3b3a6fa4d6f4ee67cc57f8a865eaa0c3 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 17:41:45 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E5=8F=8A=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/file.go | 11 +++++++++-- handler/tool.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/dao/file.go b/dao/file.go index 54b79cb..2fad62a 100644 --- a/dao/file.go +++ b/dao/file.go @@ -6,6 +6,7 @@ type File struct { gorm.Model // 存储文件名 FileStoreName string `gorm:"column:file_store_name;uniqueIndex:idx_file_name"` + NeedAuth bool `gorm:"column:need_auth"` FileName string `gorm:"column:file_name"` FileSize int `gorm:"column:file_size"` FileType string `gorm:"column:file_type"` @@ -13,8 +14,8 @@ type File struct { 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} +func CreateFile(fileStoreName, fileName, fileType, filePath string, fileSize, authID int, NeedAuth bool) uint { + file := File{FileStoreName: fileStoreName, FileName: fileName, FileType: fileType, FilePath: filePath, FileSize: fileSize, AuthID: authID, NeedAuth: NeedAuth} result := DB.Create(&file) if result.Error != nil { return 0 @@ -42,6 +43,12 @@ func FindFileByNames(fileName string, auth_id int) File { return file } +func FindFileByName(fileName string) File { + var file File + DB.Where("file_name = ?", fileName).First(&file) + return file +} + func FindFileByAuthID(auth_id int) []File { var files []File DB.Where("auth_id = ?", auth_id).Find(&files) diff --git a/handler/tool.go b/handler/tool.go index e414c89..39d512e 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -34,6 +34,7 @@ func SetUpToolGroup(router *gin.Engine) { //文件上传、下载 toolGroup.POST("/upload", UploadFile) toolGroup.GET("/download", DownloadFile) + toolGroup.GET("/file/:filename", GetFile) //文件管理 toolGroup.POST("/file_del", DelFile) //服务器、设备状态接口 @@ -97,12 +98,34 @@ func DelFile(c *gin.Context) { } +func GetFile(c *gin.Context) { + //先查看是否有权限 + filename := c.Param("filename") + if filename == "" { + c.JSON(http.StatusOK, gin.H{"error": "filename is empty", "code": proto.ParameterError, "message": "failed"}) + return + } + //查询文件信息 + file := dao.FindFileByName(filename) + if file.ID == 0 { + c.JSON(http.StatusOK, gin.H{"error": "file not found", "code": proto.FileNotFound, "message": "failed"}) + return + } + //下载文件 + if file.NeedAuth == false { + c.File(file.FilePath + "/" + file.FileStoreName) + } else { + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "file must auth", "data": "file must auth"}) + } +} + func UploadFile(c *gin.Context) { //先查看是否有权限 id, _ := c.Get("id") id1 := int(id.(float64)) //从请求头获取upload_type uploadType := c.PostForm("upload_type") + authType := c.PostForm("auth_type") if uploadType == "" { c.JSON(http.StatusOK, gin.H{"error": "upload_type is empty", "code": proto.ParameterError, "message": "failed"}) return @@ -130,7 +153,13 @@ func UploadFile(c *gin.Context) { fileSize := int(file.Size) fileName := file.Filename fileType := file.Header.Get("file_type") - fileID := dao.CreateFile(fileStoreName, fileName, fileType, filePath, fileSize, id1) + var auth_type_ bool + if authType == "public" || authType == "" { + auth_type_ = false + } else if authType == "private" { + auth_type_ = true + } + fileID := dao.CreateFile(fileStoreName, fileName, fileType, filePath, fileSize, id1, auth_type_) if fileID == 0 { c.JSON(http.StatusOK, gin.H{"error": "save file info failed", "code": proto.SaveFileInfoFailed, "message": "failed"}) return From 11f5b02559a9d0303485c4968e86ec3741277698 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 17:43:26 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E5=8F=8A=E8=8E=B7=E5=8F=96,=E4=B8=8D=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- proto/conf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/conf.go b/proto/conf.go index 6926468..9a7ff3f 100644 --- a/proto/conf.go +++ b/proto/conf.go @@ -9,7 +9,7 @@ import ( var Config ConfigStruct var SigningKey = []byte{} -var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true} // 不需要token验证的url +var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true} // 不需要token验证的url var Per_menu_map = map[string]int{"/video/": 1, "/device/": 2, "/cid/": 3} const ( From 928e7f979941f083073ea7456df6f01475ae04fa Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 18:45:48 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E6=96=87=E4=BB=B6=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/file.go | 2 +- handler/tool.go | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dao/file.go b/dao/file.go index 2fad62a..06ffc79 100644 --- a/dao/file.go +++ b/dao/file.go @@ -45,7 +45,7 @@ func FindFileByNames(fileName string, auth_id int) File { func FindFileByName(fileName string) File { var file File - DB.Where("file_name = ?", fileName).First(&file) + DB.Where("file_store_name = ?", fileName).First(&file) return file } diff --git a/handler/tool.go b/handler/tool.go index 39d512e..c6f85d6 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -164,7 +164,14 @@ func UploadFile(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"error": "save file info failed", "code": proto.SaveFileInfoFailed, "message": "failed"}) return } - c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": fileID}) + ret := map[string]interface{}{ + "file_id": fileID, + "file_store_name": fileStoreName, + "file_name": fileName, + "file_size": fileSize, + "file_type": fileType, + } + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": ret}) } From 16885ee8801055e28b5e00f4c4626f87ffe0fa20 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 19:33:59 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0file=E8=A1=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/db.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dao/db.go b/dao/db.go index 1ed2b4f..24477bb 100644 --- a/dao/db.go +++ b/dao/db.go @@ -76,6 +76,12 @@ func Init() error { return err } + err = db.AutoMigrate(&File{}) + if err != nil { + fmt.Println("file table:", err) + return err + } + err = db.AutoMigrate(&Friend{}) if err != nil { fmt.Println("friend table:", err) From 381fd3d720fbc1740056618260e7229ad5139ead Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 19:37:19 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0file=E8=A1=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/file.go b/dao/file.go index 06ffc79..058a832 100644 --- a/dao/file.go +++ b/dao/file.go @@ -5,7 +5,7 @@ import "gorm.io/gorm" type File struct { gorm.Model // 存储文件名 - FileStoreName string `gorm:"column:file_store_name;uniqueIndex:idx_file_name"` + FileStoreName string `gorm:"column:file_store_name;type:varchar(255);uniqueIndex:idx_file_name"` NeedAuth bool `gorm:"column:need_auth"` FileName string `gorm:"column:file_name"` FileSize int `gorm:"column:file_size"` From 7a650394b00252f28a6c99de65d59047f38224db Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 20:27:20 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/file.go | 16 +++++++++++++++- handler/tool.go | 14 ++++++++++++++ service/fileService.go | 12 +++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/dao/file.go b/dao/file.go index 058a832..96e4428 100644 --- a/dao/file.go +++ b/dao/file.go @@ -1,6 +1,9 @@ package dao -import "gorm.io/gorm" +import ( + "gorm.io/gorm" + "videoplayer/proto" +) type File struct { gorm.Model @@ -12,6 +15,7 @@ type File struct { FileType string `gorm:"column:file_type"` FilePath string `gorm:"column:file_path"` AuthID int `gorm:"column:auth_id"` + Md5 string `gorm:"column:md5;type:varchar(255);uniqueIndex:idx_file_name"` } func CreateFile(fileStoreName, fileName, fileType, filePath string, fileSize, authID int, NeedAuth bool) uint { @@ -82,3 +86,13 @@ func DeleteFileById(id int) bool { } return true } + +func FindFileByMd5(md5 string) File { + var file File + if proto.Config.SERVER_SQL_LOG { + DB.Debug().Where("md5 = ?", md5).First(&file) + } else { + DB.Where("md5 = ?", md5).First(&file) + } + return file +} diff --git a/handler/tool.go b/handler/tool.go index c6f85d6..9b75745 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -142,6 +142,20 @@ func UploadFile(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"error": "upload file failed", "code": proto.UploadFileFailed, "message": "failed"}) return } + //计算文件md5值 + file_, _ := file.Open() + md5Value := service.CalculateFileMd5(file_) + if md5Value == "" { + c.JSON(http.StatusOK, gin.H{"error": "计算文件MD5值失败", "code": proto.UploadFileFailed, "message": "failed"}) + return + } + //查询文件是否已存在 + fileExist := dao.FindFileByMd5(md5Value) + if fileExist.ID != 0 { + fileExist.FilePath = "" + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": fileExist}) + return + } //保存文件 filePath, fileStoreName, err := service.SaveFile(c, file, uploadType) diff --git a/service/fileService.go b/service/fileService.go index 00ca429..ee75bd6 100644 --- a/service/fileService.go +++ b/service/fileService.go @@ -1,8 +1,11 @@ package service import ( + "crypto/md5" + "fmt" "github.com/gin-gonic/gin" "github.com/google/uuid" + "io" "mime/multipart" "os" "path" @@ -34,7 +37,6 @@ func SaveFile(c *gin.Context, file *multipart.FileHeader, uploadType string) (st //生成文件路径 path_ := getFilePath(proto.FILE_BASE_DIR) filePath := path_ + "/" + fileStoreName - //保存文件 if err := c.SaveUploadedFile(file, filePath); err != nil { return "", "", err @@ -45,3 +47,11 @@ func SaveFile(c *gin.Context, file *multipart.FileHeader, uploadType string) (st 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)) +} From c9620b64dc809be6c6fc2d97449284b0bc7e63b4 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 20:30:05 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E5=80=BC=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/file.go | 4 ++-- handler/tool.go | 14 ++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/dao/file.go b/dao/file.go index 96e4428..c44c1f0 100644 --- a/dao/file.go +++ b/dao/file.go @@ -18,13 +18,13 @@ type File struct { Md5 string `gorm:"column:md5;type:varchar(255);uniqueIndex:idx_file_name"` } -func CreateFile(fileStoreName, fileName, fileType, filePath string, fileSize, authID int, NeedAuth bool) uint { +func CreateFile(fileStoreName, fileName, fileType, filePath string, fileSize, authID int, NeedAuth bool) File { file := File{FileStoreName: fileStoreName, FileName: fileName, FileType: fileType, FilePath: filePath, FileSize: fileSize, AuthID: authID, NeedAuth: NeedAuth} result := DB.Create(&file) if result.Error != nil { return 0 } - return file.ID + return file } func DeleteFileByID(id, user int) bool { diff --git a/handler/tool.go b/handler/tool.go index 9b75745..42a387c 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -173,19 +173,13 @@ func UploadFile(c *gin.Context) { } else if authType == "private" { auth_type_ = true } - fileID := dao.CreateFile(fileStoreName, fileName, fileType, filePath, fileSize, id1, auth_type_) - if fileID == 0 { + file_record := dao.CreateFile(fileStoreName, fileName, fileType, filePath, fileSize, id1, auth_type_) + if file_record.ID == 0 { c.JSON(http.StatusOK, gin.H{"error": "save file info failed", "code": proto.SaveFileInfoFailed, "message": "failed"}) return } - ret := map[string]interface{}{ - "file_id": fileID, - "file_store_name": fileStoreName, - "file_name": fileName, - "file_size": fileSize, - "file_type": fileType, - } - c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": ret}) + file_record.FilePath = "" + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": file_record}) } From fc915a0f7c10afbcb339f44e42fe2036341c39f7 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 27 Dec 2024 20:36:04 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E5=8E=BB=E9=87=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/file.go | 6 +++--- handler/tool.go | 17 ++++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/dao/file.go b/dao/file.go index c44c1f0..8133f31 100644 --- a/dao/file.go +++ b/dao/file.go @@ -18,11 +18,11 @@ type File struct { Md5 string `gorm:"column:md5;type:varchar(255);uniqueIndex:idx_file_name"` } -func CreateFile(fileStoreName, fileName, fileType, filePath string, fileSize, authID int, NeedAuth bool) File { - file := File{FileStoreName: fileStoreName, FileName: fileName, FileType: fileType, FilePath: filePath, FileSize: fileSize, AuthID: authID, NeedAuth: NeedAuth} +func CreateFile(fileStoreName, fileName, fileType, filePath, md5Str string, fileSize, authID int, NeedAuth bool) File { + file := File{FileStoreName: fileStoreName, FileName: fileName, FileType: fileType, FilePath: filePath, FileSize: fileSize, AuthID: authID, NeedAuth: NeedAuth, Md5: md5Str} result := DB.Create(&file) if result.Error != nil { - return 0 + return File{} } return file } diff --git a/handler/tool.go b/handler/tool.go index 42a387c..b1de959 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -126,6 +126,7 @@ func UploadFile(c *gin.Context) { //从请求头获取upload_type uploadType := c.PostForm("upload_type") authType := c.PostForm("auth_type") + md5_ := c.PostForm("md5") if uploadType == "" { c.JSON(http.StatusOK, gin.H{"error": "upload_type is empty", "code": proto.ParameterError, "message": "failed"}) return @@ -143,14 +144,16 @@ func UploadFile(c *gin.Context) { return } //计算文件md5值 - file_, _ := file.Open() - md5Value := service.CalculateFileMd5(file_) - if md5Value == "" { - c.JSON(http.StatusOK, gin.H{"error": "计算文件MD5值失败", "code": proto.UploadFileFailed, "message": "failed"}) - return + if md5_ == "" { + file_, _ := file.Open() + md5_ = service.CalculateFileMd5(file_) + if md5_ == "" { + c.JSON(http.StatusOK, gin.H{"error": "计算文件MD5值失败", "code": proto.UploadFileFailed, "message": "failed"}) + return + } } //查询文件是否已存在 - fileExist := dao.FindFileByMd5(md5Value) + fileExist := dao.FindFileByMd5(md5_) if fileExist.ID != 0 { fileExist.FilePath = "" c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": fileExist}) @@ -173,7 +176,7 @@ func UploadFile(c *gin.Context) { } else if authType == "private" { auth_type_ = true } - file_record := dao.CreateFile(fileStoreName, fileName, fileType, filePath, fileSize, id1, auth_type_) + file_record := dao.CreateFile(fileStoreName, fileName, fileType, filePath, md5_, fileSize, id1, auth_type_) if file_record.ID == 0 { c.JSON(http.StatusOK, gin.H{"error": "save file info failed", "code": proto.SaveFileInfoFailed, "message": "failed"}) return