up
This commit is contained in:
@@ -22,7 +22,7 @@ user:
|
||||
avatar_path: "/static/avatars/def.png"
|
||||
|
||||
file:
|
||||
max_size_mb: 50
|
||||
max_size: 52428800
|
||||
pahts:
|
||||
- "./data/avatar/"
|
||||
- "./data/upload/image/"
|
||||
@@ -32,26 +32,26 @@ file:
|
||||
- "./data/upload/other/"
|
||||
|
||||
allow_image_mime:
|
||||
- image/jpeg: true
|
||||
- image/png: true
|
||||
- image/gif: true
|
||||
- image/bmp: true
|
||||
image/jpeg: true
|
||||
image/png: true
|
||||
image/gif: true
|
||||
image/bmp: true
|
||||
|
||||
allow_video_mime:
|
||||
- video/mp4: true
|
||||
- video/x-msvideo: true
|
||||
- video/quicktime: true
|
||||
- video/x-flv: true
|
||||
- video/mpeg: true
|
||||
video/mp4: true
|
||||
video/x-msvideo: true
|
||||
video/quicktime: true
|
||||
video/x-flv: true
|
||||
video/mpeg: true
|
||||
|
||||
allow_music_mime:
|
||||
- audio/mpeg: true
|
||||
- audio/aac: true
|
||||
- audio/wav: true
|
||||
- audio/flac: true
|
||||
audio/mpeg: true
|
||||
audio/aac: true
|
||||
audio/wav: true
|
||||
audio/flac: true
|
||||
|
||||
allow_pdf_mime:
|
||||
- application/pdf: true
|
||||
application/pdf: true
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ func All_config_init() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
//fmt.Println(Configs_file)
|
||||
//fmt.Println(Allowed_avatar_mime)
|
||||
|
||||
//创建file的关键文件夹
|
||||
for _, value := range Configs_file.Pahts {
|
||||
err := os.MkdirAll(value, 0755)
|
||||
|
||||
@@ -17,10 +17,10 @@ type Configs_user_t struct {
|
||||
}
|
||||
|
||||
type Configs_file_t struct {
|
||||
Max_size_mb uint `mapstructure:"max_size_mb"`
|
||||
Pahts []string `mapstructure:"pahts"`
|
||||
Allow_image_mime []map[string]bool `mapstructure:"allow_image_mime"`
|
||||
Allow_video_mime []map[string]bool `mapstructure:"allow_video_mime"`
|
||||
Allow_music_mime []map[string]bool `mapstructure:"allow_music_mime"`
|
||||
Allow_pdf_mime []map[string]bool `mapstructure:"allow_pdf_mime"`
|
||||
Max_size uint64 `mapstructure:"max_size"`
|
||||
Pahts []string `mapstructure:"pahts"`
|
||||
Allow_image_mime map[string]bool `mapstructure:"allow_image_mime"`
|
||||
Allow_video_mime map[string]bool `mapstructure:"allow_video_mime"`
|
||||
Allow_music_mime map[string]bool `mapstructure:"allow_music_mime"`
|
||||
Allow_pdf_mime map[string]bool `mapstructure:"allow_pdf_mime"`
|
||||
}
|
||||
|
||||
+100
-15
@@ -3,6 +3,14 @@ package routers
|
||||
//文件路由
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
"saas/models"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -13,40 +21,117 @@ func Router_file(r *gin.RouterGroup) {
|
||||
|
||||
})
|
||||
|
||||
//先在中间件判断有没有登录
|
||||
//先在中间件判断有没有传进cookie
|
||||
r.Use(func(ctx *gin.Context) {
|
||||
cookie_value := ctx.PostForm("cookie")
|
||||
//fmt.Println(cookie_value)
|
||||
|
||||
ctx.Set("cookie_value", cookie_value)
|
||||
Use_login_from_cookie(ctx)
|
||||
|
||||
//先判断有没有登录
|
||||
_, is_login := ctx.Get("user_info")
|
||||
if is_login {
|
||||
|
||||
} else {
|
||||
Return_json(ctx, "user_no_sign", nil)
|
||||
if cookie_value != "" {
|
||||
ctx.Set("cookie_value", cookie_value)
|
||||
}
|
||||
|
||||
Use_login_from_cookie(ctx) //因为需要同步前端cookie,所有只能用ctx
|
||||
|
||||
})
|
||||
|
||||
upload := r.Group("/upload") //定义上传组
|
||||
//4大媒体上传接口,严格判断文件类型,可以直接被前端引用
|
||||
upload.POST("/image", func(ctx *gin.Context) {
|
||||
Return_json(ctx, "api_ok", nil)
|
||||
|
||||
//先判断有没有登录
|
||||
user_info_any, is_login := ctx.Get("user_info") //因为需要读取user_info,避免重复调用 这一步就不在中间件操作了
|
||||
if is_login {
|
||||
user_info := user_info_any.(models.User_info) //直接断言类型,这个值是从数据库直接读取的 理论不会出错
|
||||
file, err := ctx.FormFile("file")
|
||||
if err == nil {
|
||||
|
||||
//限制文件大小
|
||||
if file.Size > 512 {
|
||||
if file.Size < int64(models.Configs_file.Max_size) {
|
||||
// 2. 安全获取文件名并处理路径问题
|
||||
//filename := filepath.Base(file.Filename) // 防御性处理路径分隔符
|
||||
// 3. 获取标准后缀名(含点)
|
||||
//extWithDot := filepath.Ext(filename)
|
||||
|
||||
//判断文件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)
|
||||
if models.Configs_file.Allow_image_mime[mimeType] {
|
||||
// 打开文件流
|
||||
src, _ := file.Open()
|
||||
defer src.Close()
|
||||
// 创建SHA256哈希器
|
||||
hasher := sha256.New()
|
||||
|
||||
// 计算哈希值
|
||||
io.Copy(hasher, src)
|
||||
// 获取哈希结果
|
||||
hashBytes := hasher.Sum(nil)
|
||||
hashString := hex.EncodeToString(hashBytes)
|
||||
|
||||
new_filename := fmt.Sprintf("%d_%s", user_info.UserID, hashString)
|
||||
file.Filename = new_filename
|
||||
|
||||
//这是上传的真实路径
|
||||
dst := path.Join("./data/avatar", file.Filename)
|
||||
|
||||
//判断文件是否存在避免重复保存
|
||||
if models.File_exists(dst) {
|
||||
//fmt.Println("文件存在")
|
||||
|
||||
Return_json(ctx, "api_ok", nil)
|
||||
} else {
|
||||
//fmt.Println("文件no存在")
|
||||
ferr := ctx.SaveUploadedFile(file, dst)
|
||||
if ferr == nil {
|
||||
//文件保存成功
|
||||
|
||||
Return_json(ctx, "api_ok", nil)
|
||||
} else {
|
||||
|
||||
Return_json(ctx, "file_save_err", nil)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Return_json(ctx, "file_mime_err", nil)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Return_json(ctx, "file_size_err", nil)
|
||||
}
|
||||
} else {
|
||||
|
||||
Return_json(ctx, "file_size_err", nil)
|
||||
}
|
||||
} else {
|
||||
Return_json(ctx, "file_get_err", nil)
|
||||
}
|
||||
|
||||
} else {
|
||||
Return_json(ctx, "user_no_sign", nil)
|
||||
}
|
||||
|
||||
})
|
||||
upload.POST("/video", func(ctx *gin.Context) {
|
||||
|
||||
Return_json(ctx, "api_ok", nil)
|
||||
})
|
||||
upload.POST("/music", func(ctx *gin.Context) {
|
||||
|
||||
Return_json(ctx, "api_ok", nil)
|
||||
})
|
||||
upload.POST("/pdf", func(ctx *gin.Context) {
|
||||
|
||||
Return_json(ctx, "api_ok", nil)
|
||||
})
|
||||
//其他文件,只能通过用户报告的类型定义,不能直接被前端引用
|
||||
upload.POST("/other", func(ctx *gin.Context) {
|
||||
|
||||
Return_json(ctx, "api_ok", nil)
|
||||
})
|
||||
|
||||
// r.POST("/upload", func(ctx *gin.Context) {
|
||||
|
||||
@@ -562,13 +562,17 @@
|
||||
post_file("/image", blob, `avatar_${Date.now()}.jpg`, (c) => {
|
||||
if (c.statusCode == 200) {
|
||||
if (c.data.err_code == 0) {
|
||||
//save_json("cookie", c.data.return.cookie)
|
||||
banner_alert('success', "更换成功", 950)
|
||||
|
||||
//banner_alert('success', "更换成功", 950)
|
||||
showMessage(`✅ 上传成功!`, 'success');
|
||||
//avatar_toolt.hide();
|
||||
} else {
|
||||
banner_alert('warning', "服务错误", 3000)
|
||||
showMessage(`❌ 上传失败:`+c.data.err_msg, 'error');
|
||||
//banner_alert('warning', "服务错误", 3000)
|
||||
}
|
||||
} else {
|
||||
banner_alert('danger', "网络连接错误:" + c.statusCode, 3000)
|
||||
//banner_alert('danger', "网络连接错误:" + c.statusCode, 3000)
|
||||
showMessage(`❌ 网络连接错误:`+c.statusCode, 'error');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user