Files
ops2/backend/my_work/routers/api_Files.go
T
2026-04-28 16:43:40 +08:00

196 lines
4.9 KiB
Go

package routers
import (
"io"
"net/http"
"ops/models"
"path"
"path/filepath"
"time"
"github.com/gin-gonic/gin"
)
type TabFileInfo struct {
ID uint `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"not null;size:256;index"` // 前端报告的文件名
Size int64 `gorm:"not null"`
Path string `gorm:"not null;size:300"` //
Sha256 string `gorm:"not null;size:64;index"` //
Mime string `gorm:"size:64;index"`
Type string `gorm:"size:64;index"`
Const uint `gorm:"default:1;index"`
Per uint `gorm:"default:1"`
UserID uint `gorm:"not null;index"`
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
}
func file_save() {
}
func ApiFilesInit() {
models.DB.AutoMigrate(&TabFileInfo{})
}
func ApiFiles(r *gin.RouterGroup) {
//getfile := r.Group("/get") //定义上传组
r.GET("/:mode/:hash", func(ctx *gin.Context) {
hash := ctx.Param("hash")
mode := ctx.Param("mode")
// filename := ctx.Param("filename")
// fmt.Println(filename)
download := false
isPartOK := false
if mode == "get" {
isPartOK = true
download = true
}
if mode == "download" {
isPartOK = true
download = false
}
if isPartOK {
file_info := TabFileInfo{
Sha256: hash,
}
if models.DB.Where(&file_info).First(&file_info).Error == nil {
ReturnFile(ctx, &file_info, download)
} else {
//fmt.Println("not fund")
ReturnJson(ctx, "file_not_found", nil)
}
} else {
ReturnJson(ctx, "file_part_err", nil)
}
})
upload := r.Group("/upload") //定义上传组
//上传文件的总接口,能上传什么文件应该由后端决定,前端仅做相应限制
upload.POST("/image", func(ctx *gin.Context) {
cookie := ctx.PostForm("cookie") //首先需要判断用户是否登录
//通过cookie获取用户信息
user, err := AuthenticationAuthorityFromCookie(cookie)
if err == nil {
file, err := ctx.FormFile("file")
if err == nil {
if file.Filename != "" {
//限制文件大小
if file.Size > 512 {
if file.Size < int64(models.ConfigsFile.MaxSize) {
//判断文件mime是否合法
// 打开文件流
src_mime, _ := file.Open()
defer src_mime.Close()
// 读取前512字节用于MIME检测
buffer := make([]byte, 512)
io.ReadFull(src_mime, buffer)
// 检测MIME类型
mimeType := http.DetectContentType(buffer)
file_extname := models.ConfigsFile.AllowImageMime[mimeType]
if file_extname != "" {
filename := filepath.Base(file.Filename) // 防御性处理路径分隔符
// 计算哈希值
hash_str, err := models.SHA256HashFile(file)
if err == nil {
//fmt.Println(hash_str)
//fmt.Println(filename)
//这是上传的真实路径
dst := path.Join(models.ConfigsFile.Pahts["image"], hash_str)
//fmt.Println(dst)
//判断文件是否存在避免重复保存
if models.FileExists(dst) {
//fmt.Println("文件存在")
} else {
//fmt.Println("文件no存在")
ferr := ctx.SaveUploadedFile(file, dst)
if ferr == nil {
//文件保存成功
} else {
ReturnJson(ctx, "file_save_err", nil)
ctx.Abort() //end
return
}
}
//记录到数据库
//先检查数据库有没有数据
fund_file_info := TabFileInfo{
Name: filename,
Size: file.Size,
Sha256: hash_str,
Mime: mimeType,
Type: "image",
UserID: user.ID,
}
fund_file_info2 := TabFileInfo{}
models.DB.Where(&fund_file_info).Find(&fund_file_info2)
if fund_file_info2.ID != 0 {
fund_file_info2.Const += 1
models.DB.Where(&fund_file_info).Updates(&fund_file_info2)
} else {
fund_file_info.Path = dst
models.DB.Create(&fund_file_info) // 传入指针
}
//返回后台存储的URL
download_URL := path.Join("/api/files/download/", hash_str)
get_URL := path.Join("/api/files/get/", hash_str)
re := map[string]interface{}{
"download": download_URL,
"get": get_URL,
"hash": hash_str,
}
ReturnJson(ctx, "apiOK", re)
} else {
ReturnJson(ctx, "file_hash_err", nil)
}
} else {
ReturnJson(ctx, "file_mime_err", nil)
}
} else {
ReturnJson(ctx, "file_size_err", nil)
}
} else {
ReturnJson(ctx, "file_size_err", nil)
}
} else {
ReturnJson(ctx, "file_name_err", nil)
}
} else {
ReturnJson(ctx, "file_get_err", nil)
}
} else {
ReturnJson(ctx, "userCookieError", nil)
}
//ReturnJson(ctx, "apiErr", nil)
})
// r.GET("/upload", func(ctx *gin.Context) {
// ReturnJson(ctx, "apiOK", nil)
// })
}