Merge branch 'refs/heads/feat-file' into release
This commit is contained in:
commit
aac77e078a
|
|
@ -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)
|
||||
|
|
|
|||
33
dao/file.go
33
dao/file.go
|
|
@ -1,25 +1,30 @@
|
|||
package dao
|
||||
|
||||
import "gorm.io/gorm"
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"videoplayer/proto"
|
||||
)
|
||||
|
||||
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"`
|
||||
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) uint {
|
||||
file := File{FileStoreName: fileStoreName, FileName: fileName, FileType: fileType, FilePath: filePath, FileSize: fileSize, AuthID: authID}
|
||||
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.ID
|
||||
return file
|
||||
}
|
||||
|
||||
func DeleteFileByID(id, user int) bool {
|
||||
|
|
@ -42,6 +47,12 @@ func FindFileByNames(fileName string, auth_id int) File {
|
|||
return file
|
||||
}
|
||||
|
||||
func FindFileByName(fileName string) File {
|
||||
var file File
|
||||
DB.Where("file_store_name = ?", fileName).First(&file)
|
||||
return file
|
||||
}
|
||||
|
||||
func FindFileByAuthID(auth_id int) []File {
|
||||
var files []File
|
||||
DB.Where("auth_id = ?", auth_id).Find(&files)
|
||||
|
|
@ -75,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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,35 @@ 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")
|
||||
md5_ := c.PostForm("md5")
|
||||
if uploadType == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"error": "upload_type is empty", "code": proto.ParameterError, "message": "failed"})
|
||||
return
|
||||
|
|
@ -119,6 +143,22 @@ func UploadFile(c *gin.Context) {
|
|||
c.JSON(http.StatusOK, gin.H{"error": "upload file failed", "code": proto.UploadFileFailed, "message": "failed"})
|
||||
return
|
||||
}
|
||||
//计算文件md5值
|
||||
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(md5_)
|
||||
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)
|
||||
|
|
@ -130,12 +170,19 @@ 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)
|
||||
if fileID == 0 {
|
||||
var auth_type_ bool
|
||||
if authType == "public" || authType == "" {
|
||||
auth_type_ = false
|
||||
} else if authType == "private" {
|
||||
auth_type_ = true
|
||||
}
|
||||
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
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": fileID})
|
||||
file_record.FilePath = ""
|
||||
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": file_record})
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue