gin框架post路由

2019年3月22日 发表评论 阅读评论

由于本篇的内容需要涉及到一些静态资源的加载(get方法中打开的html页面),所以我们先进行静态资源配置,这里主要使用LoadHTMLGlob 加载html模板文件,使用StaticFS方法css、js及上传的文件。具体如下:

func setStaticFS(r *gin.Engine) {
	r.LoadHTMLGlob("views/*")
	r.StaticFS("/static", http.Dir("public/static"))
	r.StaticFS("/upload", http.Dir("upload"))
}

一、post请求的分类

常用请求Headers中Content-Type的类型有text/plain、text/html、application/json、application/x-www-form-urlencoded、application/xml和multipart/form-data等。具体如下:

text/plain 纯文本
text/html HTML文档
application/json json格式数据
application/x-www-form-urlencoded 使用HTTP的POST方法提交的表单
application/xml xml格式数据
application/form-data主要是用来上传文件

二、API分组

gin提供了分组功能,便于把一些功能模块集中到一起,通过同一请求的URL前缀进行处理,我们使用分组功能,先把框架写出来,再构建具体的函数,如下:

api := r.Group("/api")
{
	api.POST("/form_post", formPost)
	api.POST("/json_post", jsonPost)
	api.POST("/urlencoded_post", urlencodedPost)
	api.POST("/json_and_form_post", jsonAndFormPost)
	api.POST("/xml_post", xmlPost)
	api.POST("/file_upload", fileUpload)
	api.GET("/list", func(c *gin.Context) {
		message := c.Query("message")
		nick := c.DefaultQuery("nick", "anonymous")
		c.JSON(http.StatusOK, gin.H{
			"status":  "SUCCESS",
			"message": message,
			"nick":    nick,
		})
	})
}

通过该操作,我们完成了api路由分组。

三、功能实现

1、form 表单提交

上面路由分组中的/api/form_post调用的是后面的formPost方法,我们通过如下代码实现该方法:

api.POST("/form_post", formPost)
// 表单提交
func formPost(c *gin.Context) {
	message := c.PostForm("message")
	nick := c.DefaultPostForm("nick", "anonymous") // 没有获取到nick值时给一个默认值
	log.Println(message, nick)
	c.JSON(http.StatusOK, gin.H{
		"status":  "SUCCESS",
		"message": message,
		"nick":    nick,
	})
}

在html页面中我们可以按如下方式调用:

<form method="post" action="/api/form_post">
	<input type="text" name="message">
	<input type="text" name="nick">
	<button type="submit">提交</button>
</form>

2、post json数据

jsonPost方法如下:

type User struct {
	Name    string `json:"name" form:"name"`
	Message string `json:"message" form:"message"`
	Nick    string `json:"nick" form:"nick"`
}
func jsonPost(c *gin.Context) {
	var user User
	c.BindJSON(&user)
	log.Println(user.Name, user.Message, user.Nick)
	c.JSON(http.StatusOK, gin.H{
		"status":  "SUCCESS",
		"name":    user.Name,
		"message": user.Message,
		"nick":    user.Nick,
	})
}

能过js调用代码如下:

$('.json').on('click', function() {
	axios({
  		method: 'post',
	  	url: '/api/json_post',
	  	headers: {
	  		'Content-Type': 'application/json'
	  	},
	  	data
	}).then(res => {
		console.log(res.data)
		$('.json-msg').text(`success  ${new Date()}`)
	})
})

3、post x-www-form-urlencoded数据

// application/x-www-form-urlencoded
func urlencodedPost(c *gin.Context) {
	name := c.Query("name")
	message := c.PostForm("message")
	nick := c.DefaultPostForm("nick", "1231412")
	log.Println(name, message, nick)
	c.JSON(http.StatusOK, gin.H{
		"status":  "SUCCESS",
		"name":    name,
		"message": message,
		"nick":    nick,
	})
}

JS调用如下:

$('.urlencoded').on('click', function() {
	var data = {}
	var inputs = $('#form input')
	for (let i = 0; i < inputs.length; i ++) {
		data[$(inputs[i]).attr('name')] = $(inputs[i]).val()
	}
	axios({
 	 	method: 'post',
	  	url: '/api/urlencoded_post?name=361way.com',
	  	headers: {
	  		'Content-Type': 'application/x-www-form-urlencoded'
	  	},
	  	data: $.param(data)
	}).then(res => {
		console.log(res.data)
		$('.urlencoded-msg').text(`success  ${new Date()}`)
	})
})

4、通过bind方法同时支持post和form-urlencoded

也存在一些情况,我们不知道post过来的数据类型,我们想要同时支持两者,可以使用gin中的bind方法,具体代码如下:

type User struct {
	Name    string `json:"name" form:"name"`
	Message string `json:"message" form:"message"`
	Nick    string `json:"nick" form:"nick"`
}
// application/json  application/x-www-form-urlencoded
func jsonAndFormPost(c *gin.Context) {
	var user User
	c.Bind(&user)
	log.Println(user.Name, user.Message, user.Nick)
	c.JSON(http.StatusOK, gin.H{
		"status":  "SUCCESS",
		"name":    user.Name,
		"message": user.Message,
		"nick":    user.Nick,
	})
}

可以看到上面的代码中,我们对结构体的定义同时指定了json 和 form。对应的js我们也需要进行修改判断,如下:

$('.jsonandform').on('click', function() {
	var data = {}
	var inputs = $('#form input')
	for (let i = 0; i < inputs.length; i ++) {
		data[$(inputs[i]).attr('name')] = $(inputs[i]).val()
	}
	axios({
  		method: 'post',
	  	url: '/api/json_and_form_post',
	  	headers: {
	  		'Content-Type': 'application/json'
	  	},
	  	data
	}).then(res => {
		console.log(res.data)
		$('.jsonandform-msg').text(`success application/json data,  ${new Date()}`)
	})
})
$('.jsonandform2').on('click', function() {
	var data = {}
	var inputs = $('#form input')
	for (let i = 0; i < inputs.length; i ++) {
		data[$(inputs[i]).attr('name')] = $(inputs[i]).val()
	}
	axios({
  		method: 'post',
	  	url: '/api/json_and_form_post',
	  	headers: {
	  		'Content-Type': 'application/x-www-form-urlencoded'
	  	},
	  	data:$.param(data)
	}).then(res => {
		console.log(res.data)
		$('.jsonandform-msg').text(`success application/x-www-form-urlencoded data${new Date()}`)
	})
})

5、post xml格式数据

type User struct {
	Name    string `json:"name" form:"name" xml:"name"`
	Message string `json:"message" form:"message" xml:"message"`
	Nick    string `json:"nick" form:"nick" xml:"nick"`
}
func xmlPost(c *gin.Context) {
	var user User
	c.Bind(&user)
	log.Println(user.Name, user.Message, user.Nick)
	c.JSON(http.StatusOK, gin.H{
		"status":  "SUCCESS",
		"name":    user.Name,
		"message": user.Message,
		"nick":    user.Nick,
	})
}

js调用如下:

$('.xml_post').on('click', function() {
	var data = {}
	var inputs = $('#form input')
	for (let i = 0; i < inputs.length; i ++) {
		data[$(inputs[i]).attr('name')] = $(inputs[i]).val()
	}
	axios({
		method: 'post',
		url: '/api/xml_post',
		headers: {
			"Content-Type": 'application/xml'
		},
		data: `<xml><name>${data.name}</name><message>${data.message}</message><nick>${data.nick}</nick></xml>`
	})
})

6、post multipart/form-data

gin实现文件上传代码如下:

func fileUpload(c *gin.Context) {
	filesUrl := make([]string, 0)
	form, err := c.MultipartForm()
	if err != nil {
		log.Println("postMultipleFile error: %s")
	}
	files := form.File["file"]
	_, err = os.Stat("upload")
	if err != nil {
		os.Mkdir("upload", os.ModePerm)
	}
	for _, file := range files {
		log.Println(file.Filename)
		// Upload the file to specific dst.
		if err = c.SaveUploadedFile(file, "upload/"+file.Filename); err != nil {
			log.Println("SaveUploadedFile error: %s")
			return
		}
		filesUrl = append(filesUrl, "upload/"+file.Filename)
	}
	c.JSON(http.StatusOK, gin.H{
		"state": "SUCCESS",
		"url":   strings.Join(filesUrl, ";"),
	})
}

html实现:

<div>
	<form id="multipleForm">
		<input type="file" name="file" id='file' multiple="multiple" accept="image/*">
	</form>
	<button class="file_upload">上传文件</button>
</div>

js实现:

$('.file_upload').on('click', function () {
	// 单个文件上传
	// var fd = new FormData()
	// var file = document.getElementById('file')
	// fd.append('file', file.files[0])
	axios({
  		method: 'post',
	  	url: '/api/file_upload',
	  	headers: {
	  		'Content-Type': 'application/form-data'
	  	},
	  	// data:fd
	  	data: new FormData($('#multipleForm')[0])
	}).then(res => {
		console.log(res.data)
		const urls = res.data.url.split(';')
		let imgHtml = '';
		for(let i = 0; i < urls.length; i ++) {
			imgHtml += `<img style="width: 200px" src="/${urls[i]}" />`
		}
		$('.file_upload-msg').html(`<div>success ${new Date()} 文件地址/${res.data.url} ${imgHtml}</div>`)
	})
})

完整代码:https://github.com/361way/golang/tree/master/gin/gin_rotuer_web




本站的发展离不开您的资助,金额随意,欢迎来赏!

You can donate through PayPal.
My paypal id: itybku@139.com
Paypal page: https://www.paypal.me/361way

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.