go gin ShouldBind 绑定参数到结构体struct 数据校验 文件上传 fmt.Sprintf拼接字符串 path.Ext获取文件后缀名 goto
数据校验部分参考https://juejin.cn/post/6863765115456454664#heading-7,没有使用 github.com/go-playground/validator/v10,进行更复杂的校验时可以使用。
·
数据校验部分参考https://juejin.cn/post/6863765115456454664#heading-7,没有使用 github.com/go-playground/validator/v10,进行更复杂的校验时可以使用
ShouldBind 可以i绑定各种请求的参数到对应的结构体上
- 结构体的field必须大写字母开头,否则该field无法绑定
- form:“age” 表示请求的参数的key是age,比如此时/b1/age=1可以绑定到user.Age,/b1/Age=1不可以绑定
- json:“age” 表示把u以json返回时,Age的key是age
- binding:“required” 表示此字段绑定失败会提示错误。不终止程序,其他字段能继续绑定
- min/max:字符串的最小/大位数
- lte/gte/lt/gt: 小于等于/大于等于/小于/大于
- email:需要email格式
- eqfield=AnotherFiled:本字段的值需要等于AnotherFiled字段的值
- oneof=m f:需要是m或者f中的一个
文件上传
- MultipartForm处理多个或者单个文件,FormFile单个文件,推荐MultipartForm
- MultipartForm的返回值是*multipart.Form,此结构体有两个field,分别是Value map[string][]string和File map[string][]*FileHeader
- 代码里,key是html文件里file的name属性,file_是[]*FileHeader(FileHeader切片),所以取得文件要用file_[0]
- fmt.Sprintf用来拼接字符串,类似python的"xxx{}xx".format
- path.Ext获取文件后缀名
前端传多个文件,且不同文件对应不同的name,可以用这个代码。
如果多个文件用同一个name以数组的形式传递,只能获取第一个文件。此时代码参考https://blog.csdn.net/weixin_43292547/article/details/126933263
package main
import (
"fmt"
"html/template"
"log"
"mime/multipart"
"net/http"
"path"
"time"
"github.com/gin-gonic/gin"
)
func main() {
mainGin()
}
func mainGin() {
r := gin.Default()
//据说可以限制文件大小,不起作用
// r.MaxMultipartMemory=1 << 20 //1*(2^10)*(2^10)=1m
r.MaxMultipartMemory= 1
r.Any("/b2", func(c *gin.Context) {
c.HTML(http.StatusOK, "upload.html", nil)
})
r.Any("/b1", func(c *gin.Context) {
type user struct {
Name string `binding:"required,min=2,max=4"`
Age int8 `form:"age" json:"age" binding:"required,gte=1,lte=9"`
Weight float32
Email string `binding:"required,email"`
Email2 string `binding:"required,eqfield=Email"`
Gender string `binding:"required,oneof=m f"`
}
var (
u user
f *multipart.Form
err error
)
if err = c.ShouldBind(&u); err != nil {
goto End
} else {
log.Println(u)
}
// 上传多个文件或单个文件
f, err = c.MultipartForm()
//fmt.Printf("\nf:%v", f)
if err != nil {
goto End
} else {
files:=f.File
//fmt.Printf("\nfiles:%v", files)
//这里key是html文件里file的name属性,file_是[]*FileHeader(FileHeader切片)
for key, file_ := range files{
f:=file_[0]
//fmt.Printf("\n key:%s:%s", key,f.Filename)
//path.Ext获取文件后缀名
dest := fmt.Sprintf("./upload/%d-%s%s", time.Now().Unix(),key,path.Ext(f.Filename))
//fmt.Println(dest)
if err = c.SaveUploadedFile(f, dest); err != nil {
goto End
}
}
}
// 上传单个文件
// f, err = c.FormFile("file1")
// if err != nil {
// goto End
// } else {
// dest := path.Join("./upload", f.Filename)
// fmt.Println(dest)
// if err = c.SaveUploadedFile(f, dest); err != nil {
// goto End
// }
// }
End:
if err != nil {
c.JSON(http.StatusOK, gin.H{"err": err.Error()})
} else {
c.JSON(http.StatusOK, u)
}
})
//template\upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form method='post' action='b1' enctype='multipart/form-data'>
<input name="Name" value="aa"/><br/>
<input name="age" value="3"/><br/>
<input name="Weight" value="2.3"/><br/>
<input name="Email" value="1@a.c"/><br/>
<input name="Email2" value="1@a.c"/><br/>
<input name="Gender" value="m"/><br/>
<input name="file1" type="file"/><br/>
<input name="file2" type="file"/><br/>
<button type="submit">submit</button><br/>
</form>
</body>
</html>
更多推荐
已为社区贡献8条内容
所有评论(0)