后端接收ok

This commit is contained in:
2026-01-19 21:32:09 +08:00
parent 6396b79ac5
commit 6ecc3beaef
6 changed files with 169 additions and 23 deletions
+5 -1
View File
@@ -13,7 +13,11 @@
"file_mime_err":-51, "file_mime_err":-51,
"file_size_err":-52, "file_size_err":-52,
"file_name_err":-53, "file_name_err":-53,
"file_get_err":-54 "file_get_err":-54,
"file_hash_err":-55,
"file_save_err":-56,
"file_not_found":-57,
"file_part_err":-58
} }
+1 -1
View File
@@ -16,7 +16,7 @@ type TabFileInfo_ struct {
ID uint `gorm:"primaryKey;autoIncrement"` ID uint `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"not null;size:256;index"` // 前端报告的文件名 Name string `gorm:"not null;size:256;index"` // 前端报告的文件名
Path string `gorm:"not null;size:300"` // Path string `gorm:"not null;size:300"` //
Sha256 string `gorm:"not null;size:256;index"` // Sha256 string `gorm:"not null;size:64;index"` //
Mime string `gorm:"size:64;index"` Mime string `gorm:"size:64;index"`
Type string `gorm:"size:64;index"` Type string `gorm:"size:64;index"`
Const uint `gorm:"default:1;index"` Const uint `gorm:"default:1;index"`
+143 -10
View File
@@ -1,7 +1,11 @@
package routers package routers
import ( import (
"fmt" "io"
"net/http"
"ops/models"
"path"
"path/filepath"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -11,22 +15,151 @@ func file_save() {
} }
func ApiFiles(r *gin.RouterGroup) { func ApiFiles(r *gin.RouterGroup) {
r.POST("/upload", func(ctx *gin.Context) {
cookie := ctx.PostForm("cookie") //getfile := r.Group("/get") //定义上传组
file, _ := ctx.FormFile("file") 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 := models.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获取用户信息 //通过cookie获取用户信息
_, err := AuthenticationAuthorityFromCookie(cookie) user, err := AuthenticationAuthorityFromCookie(cookie)
if err == nil { 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 := models.TabFileInfo_{
Name: filename,
Sha256: hash_str,
Mime: mimeType,
Type: "image",
UserID: user.ID,
}
fund_file_info2 := models.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) // 传入指针
} }
fmt.Println(file.Filename)
fmt.Println(cookie)
ReturnJson(ctx, "apiOK", nil)
})
r.GET("/upload", func(ctx *gin.Context) {
ReturnJson(ctx, "apiOK", nil) ReturnJson(ctx, "apiOK", nil)
} 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)
// })
} }
+8 -4
View File
@@ -1,6 +1,10 @@
package routers package routers
import "github.com/gin-gonic/gin" import (
"ops/models"
"github.com/gin-gonic/gin"
)
func ReturnJson(ctx *gin.Context, errMsg string, data map[string]interface{}) { func ReturnJson(ctx *gin.Context, errMsg string, data map[string]interface{}) {
var errCode = ErrorCode[errMsg] var errCode = ErrorCode[errMsg]
@@ -23,12 +27,12 @@ func ReturnJson(ctx *gin.Context, errMsg string, data map[string]interface{}) {
} }
func Return_file(ctx *gin.Context, file_path string, preview bool) { func ReturnFile(ctx *gin.Context, file_info *models.TabFileInfo_, preview bool) {
if preview { if preview {
ctx.File(file_path) ctx.File(file_info.Path)
} else { } else {
//需要从数据库拉取原始文件名 //需要从数据库拉取原始文件名
//ctx.FileAttachment(file_info.Path, file_info.Name) ctx.FileAttachment(file_info.Path, file_info.Name)
} }
} }
@@ -24,7 +24,11 @@ const prop= defineProps({
maxFilesize:{ maxFilesize:{
type: Number, type: Number,
default: 10, default: 10,
} },
uploadURL:{
type: String,
default: "/api/files/upload",
},
}); });
// 初始化 Dropzone // 初始化 Dropzone
@@ -41,7 +45,7 @@ const initDropzone = () => {
// 初始化新的实例 // 初始化新的实例
dropzoneInstance = new Dropzone(dropzoneElement.value, { dropzoneInstance = new Dropzone(dropzoneElement.value, {
url: "/api/files/upload", // 上传地址 url: prop.uploadURL, // 上传地址
// headers: { // headers: {
// user_cookie: "cccc", // user_cookie: "cccc",
// }, // },
@@ -139,13 +139,14 @@ watch(locale, () => {
>{{ t("purchase_addorder.remarks") }} >{{ t("purchase_addorder.remarks") }}
<span class="form-label-description">0/100</span></label <span class="form-label-description">0/100</span></label
> >
<useDropzone></useDropzone>
<textarea <textarea
class="form-control mt-2" class="form-control mt-2 mb-2"
name="example-textarea-input" name="example-textarea-input"
rows="6" rows="6"
:placeholder="t('purchase_addorder.remarks_text')" :placeholder="t('purchase_addorder.remarks_text')"
></textarea> ></textarea>
<useDropzone acceptedFiles="image/*" uploadURL="/api/files/upload/image" maxFiles="10"></useDropzone>
</div> </div>
</div> </div>