From ef2d1dbbc4a6d4c6d8007d7d26ce343a52776890 Mon Sep 17 00:00:00 2001 From: viletyy Date: Sat, 26 Sep 2020 19:06:41 +0800 Subject: [PATCH] =?UTF-8?q?[ADD]=E4=B8=8A=E4=BC=A0=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/app.ini | 2 +- docs/docs.go | 35 +++++++++++++++++ docs/swagger.json | 35 +++++++++++++++++ docs/swagger.yaml | 23 ++++++++++++ models/employee.go | 3 +- pkg/e/code.go | 21 ++++++----- pkg/e/msg.go | 21 ++++++----- pkg/upload/image.go | 83 +++++++++++++++++++++++++++++++++++++++++ pkg/util/md5.go | 13 +++++++ routers/admin.go | 2 + routers/admin/upload.go | 64 +++++++++++++++++++++++++++++++ routers/api.go | 1 - 12 files changed, 282 insertions(+), 21 deletions(-) create mode 100644 pkg/upload/image.go create mode 100644 pkg/util/md5.go create mode 100644 routers/admin/upload.go delete mode 100644 routers/api.go diff --git a/conf/app.ini b/conf/app.ini index 774bf21..2d94890 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -5,7 +5,7 @@ JwtSecret = 233 RuntimeRootPath = runtime/ ImagePrefixUrl = http://127.0.0.8002 ImageSavePath = upload/images/ -ImageMaxSize = 5 +ImageMaxSize = 1024 ImageAllowExts = .jpg,.jpeg,.png logSavePath = logs/ diff --git a/docs/docs.go b/docs/docs.go index 0c45f89..a1a5fd2 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -266,6 +266,41 @@ var doc = `{ } } } + }, + "/admin/v1/upload": { + "post": { + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "summary": "上传图片", + "parameters": [ + { + "type": "string", + "description": "auth by /admin/login", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "type": "file", + "description": "imageFile", + "name": "image", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":200,\"data\":{},\"msg\":\"ok\"}", + "schema": { + "type": "string" + } + } + } + } } } }` diff --git a/docs/swagger.json b/docs/swagger.json index 7b3fc45..aeaa11e 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -246,6 +246,41 @@ } } } + }, + "/admin/v1/upload": { + "post": { + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "summary": "上传图片", + "parameters": [ + { + "type": "string", + "description": "auth by /admin/login", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "type": "file", + "description": "imageFile", + "name": "image", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":200,\"data\":{},\"msg\":\"ok\"}", + "schema": { + "type": "string" + } + } + } + } } } } \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 5ab2b00..18c4033 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -163,4 +163,27 @@ paths: summary: 更新员工 tags: - employees + /admin/v1/upload: + post: + consumes: + - multipart/form-data + parameters: + - description: auth by /admin/login + in: header + name: Authorization + required: true + type: string + - description: imageFile + in: formData + name: image + required: true + type: file + produces: + - application/json + responses: + "200": + description: '{"code":200,"data":{},"msg":"ok"}' + schema: + type: string + summary: 上传图片 swagger: "2.0" diff --git a/models/employee.go b/models/employee.go index 12a2ac6..1144c00 100644 --- a/models/employee.go +++ b/models/employee.go @@ -2,6 +2,7 @@ package models type Employee struct { Model + AvatarUrl string `json:"avatar_url"` Username string `json:"username"` Password string `json:"password"` Department string `json:"department"` @@ -75,4 +76,4 @@ func CleaanAllEmployee() bool { db.Unscoped().Where("deleted_on != ?", 0).Delete(&Employee{}) return true -} \ No newline at end of file +} diff --git a/pkg/e/code.go b/pkg/e/code.go index 0c1240d..8af0e6c 100644 --- a/pkg/e/code.go +++ b/pkg/e/code.go @@ -1,14 +1,17 @@ package e const ( - SUCCESS = 200 - ERROR = 500 - InvalidParams = 400 - ErrorAuthCheckTokenFail = 10001 - ErrorAuthCheckTokenTimeout = 10002 - ErrorAuthToken = 10003 - ErrorAuth = 10004 + SUCCESS = 200 + ERROR = 500 + InvalidParams = 400 + ErrorAuthCheckTokenFail = 10001 + ErrorAuthCheckTokenTimeout = 10002 + ErrorAuthToken = 10003 + ErrorAuth = 10004 + ErrorUploadSaveImageFail = 10005 + ErrorUploadCheckImageFail = 10006 + ErrorUploadCheckImageFormat = 10007 - ErrorExistEmployee = 20001 - ErrorNotExistEmployee = 20002 + ErrorExistEmployee = 20001 + ErrorNotExistEmployee = 20002 ) diff --git a/pkg/e/msg.go b/pkg/e/msg.go index f2e1bea..1e6a002 100644 --- a/pkg/e/msg.go +++ b/pkg/e/msg.go @@ -1,15 +1,18 @@ package e var MsgFlags = map[int]string{ - SUCCESS: "ok", - ERROR: "fail", - InvalidParams: "请求参数错误", - ErrorAuthCheckTokenFail: "TOKEN鉴权失败", - ErrorAuthCheckTokenTimeout: "TOKEN已超时", - ErrorAuthToken: "TOKEN生成失败", - ErrorAuth: "TOKEN错误", - ErrorExistEmployee: "已存在该员工用户名", - ErrorNotExistEmployee: "该员工不存在", + SUCCESS: "ok", + ERROR: "fail", + InvalidParams: "请求参数错误", + ErrorAuthCheckTokenFail: "TOKEN鉴权失败", + ErrorAuthCheckTokenTimeout: "TOKEN已超时", + ErrorAuthToken: "TOKEN生成失败", + ErrorAuth: "TOKEN错误", + ErrorUploadSaveImageFail: "保存图片错误", + ErrorUploadCheckImageFail: "检查图片失败", + ErrorUploadCheckImageFormat: "校验图片错误,图片格式或大小有问题", + ErrorExistEmployee: "已存在该员工用户名", + ErrorNotExistEmployee: "该员工不存在", } func GetMsg(code int) string { diff --git a/pkg/upload/image.go b/pkg/upload/image.go new file mode 100644 index 0000000..b82ea87 --- /dev/null +++ b/pkg/upload/image.go @@ -0,0 +1,83 @@ +package upload + +import ( + "fmt" + "github.com/go-pripro/shop/pkg/file" + "github.com/go-pripro/shop/pkg/logging" + "github.com/go-pripro/shop/pkg/setting" + "github.com/go-pripro/shop/pkg/util" + "log" + "mime/multipart" + "os" + "path" + "strings" +) + +// 获取图片完整访问URL +func GetImageFullUrl(name string) string { + return setting.AppSetting.ImagePrefixUrl + "/" + GetImagePath() + name +} + +// 获取图片名称 +func GetImageName(name string) string { + ext := path.Ext(name) + fileName := strings.TrimSuffix(name, ext) + fileName = util.EncodeMD5(fileName) + + return fileName + ext +} + +// 获取图片路径 +func GetImagePath() string { + return setting.AppSetting.ImageSavePath +} + +// 获取图片完整路径 +func GetImageFullPath() string { + return setting.AppSetting.RuntimeRootPath + GetImagePath() +} + +// 检查图片后缀 +func CheckImageExt(fileName string) bool { + ext := file.GetExt(fileName) + for _, allowExt := range setting.AppSetting.ImageAllowExts { + if strings.ToUpper(allowExt) == strings.ToUpper(ext) { + return true + } + } + + return false +} + +// 检查图片大小 +func CheckImageSize(f multipart.File) bool { + size, err := file.GetSize(f) + logging.Info(size) + if err != nil { + log.Println(err) + logging.Warn(err) + return false + } + + return size <= setting.AppSetting.ImageMaxSize*1024*1024 +} + +// 检查图片 +func CheckImage(src string) error { + dir, err := os.Getwd() + if err != nil { + return fmt.Errorf("os.Getwd err:%v", err) + } + + err = file.IsNotExistMkDir(dir + "/" + src) + if err != nil { + return fmt.Errorf("file.IsNotExistMkDir err: %v", err) + } + + perm := file.CheckPermission(src) + if perm == true { + return fmt.Errorf("file.CheckPermission Permission denied src: %s", src) + } + + return nil +} \ No newline at end of file diff --git a/pkg/util/md5.go b/pkg/util/md5.go new file mode 100644 index 0000000..d189e62 --- /dev/null +++ b/pkg/util/md5.go @@ -0,0 +1,13 @@ +package util + +import ( + "crypto/md5" + "encoding/hex" +) + +func EncodeMD5(value string) string { + m := md5.New() + m.Write([]byte(value)) + + return hex.EncodeToString(m.Sum(nil)) +} \ No newline at end of file diff --git a/routers/admin.go b/routers/admin.go index d31b396..e677f59 100644 --- a/routers/admin.go +++ b/routers/admin.go @@ -14,6 +14,8 @@ func InitAdmin(r *gin.Engine) *gin.Engine { adminv1 := r.Group("/admin/v1") adminv1.Use(jwt.JWT()) { + // 上传图片 + adminv1.POST("/upload", admin.UploadImage) // 获取员工列表 adminv1.GET("/employees", v1.GetEmployees) // 获取指定员工列表 diff --git a/routers/admin/upload.go b/routers/admin/upload.go new file mode 100644 index 0000000..c7b4d86 --- /dev/null +++ b/routers/admin/upload.go @@ -0,0 +1,64 @@ +package admin + +import ( + "github.com/gin-gonic/gin" + "github.com/go-pripro/shop/pkg/e" + "github.com/go-pripro/shop/pkg/logging" + "github.com/go-pripro/shop/pkg/upload" + "net/http" +) + +// @Summary 上传图片 +// @Description +// @Accept mpfd +// @Produce json +// @Param Authorization header string true "auth by /admin/login" +// @Param image formData file true "imageFile" +// @Success 200 {string} json "{"code":200,"data":{},"msg":"ok"}" +// @Router /admin/v1/upload [post] +func UploadImage(c *gin.Context) { + code := e.SUCCESS + data := make(map[string]string) + + file, image, err := c.Request.FormFile("image") + if err != nil { + logging.Warn(err) + code = e.ERROR + c.JSON(http.StatusOK, gin.H{ + "code": code, + "msg": e.GetMsg(code), + "data": data, + }) + } + + if image == nil { + code = e.InvalidParams + } else { + imageName := upload.GetImageName(image.Filename) + fullPath := upload.GetImageFullPath() + savePath := upload.GetImagePath() + + src := fullPath + imageName + if !upload.CheckImageExt(imageName) || !upload.CheckImageSize(file) { + code = e.ErrorUploadCheckImageFormat + } else { + err := upload.CheckImage(fullPath) + if err != nil { + logging.Warn(err) + code = e.ErrorUploadCheckImageFail + } else if err := c.SaveUploadedFile(image, src); err != nil { + logging.Warn(err) + code = e.ErrorUploadSaveImageFail + } else { + data["image_url"] = upload.GetImageFullUrl(imageName) + data["image_save_url"] = savePath + imageName + } + } + } + + c.JSON(http.StatusOK, gin.H{ + "code" : code, + "msg" : e.GetMsg(code), + "data" : data, + }) +} diff --git a/routers/api.go b/routers/api.go deleted file mode 100644 index 159906f..0000000 --- a/routers/api.go +++ /dev/null @@ -1 +0,0 @@ -package routers