golang学习之gin(四):参数绑定、文件上传、其他数据格式输出、自定义HTTP配置
2023-09-27 14:29:29 时间
文章目录
一、参数绑定:
1. 什么是参数绑定:
能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象
2. ShouldBind:
./
├── chapter04
│ └── post.go
├── main.go
│ ├── css
│ │ └── index.css
│ ├── images
│ └── js
└── template
├── chapter04
│ └── user_add.html
./main.go
package main
import (
"gin_project/chapter04"
"github.com/gin-gonic/gin"
)
func main() {
engine := gin.Default()
// 注册模板
engine.LoadHTMLGlob("template/**/*")
// 注册静态文件
engine.Static("./static", "static")
// 注册路由
// POST
engine.GET("/to_user_add", chapter04.ToUserAdd4) // 获取请求页面
engine.POST("/user_add", chapter04.PostForm4)
engine.Run(":9000")
}
./chapter04/post.go
package chapter04
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
// structTag:指定字段名称,不用使用首字母大写的
Id int `form:"id" json:"id"`
Name string `form:"username" json:"username`
Age string `form:"age" json:"age`
Address string `form:"address" json:"address"`
}
// post
func ToUserAdd4(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "chapter04/user_add.html", nil)
}
func PostForm4(ctx *gin.Context) {
var userInfo User
err := ctx.ShouldBind(&userInfo)
fmt.Println(err) //<nil>
fmt.Println(userInfo) // {0 user 12 西三旗}
ctx.String(http.StatusOK, "hello")
}
./template/chapter04/user_add.html
{{ define "chapter04/user_add.html" }}
<!DOCTYPE html>
<html lang="zh">
<head>
<title>post请求练习</title>
<style>
.userForm {
width: 480px;
height: 360px;
margin: 20px 200px;
}
input {
margin: 5px 0;
}
</style>
</head>
<body>
<div class="userForm">
<h2>添加用户</h2>
<form action="/user_add" method="post">
<span>用户名: </span><input type="text" name="username"><br>
<span>年 龄: </span><input type="text" name=" "><br>
<span>地 址: </span><input type="text" name="address"><br>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
{{ end }}
3. ShouldBindWith
可以使用显式绑定声明绑定 multipart form:
c.ShouldBindWith(&form, binding.Form)
或者简单地使用 ShouldBind 方法自动绑定
4. ShouldBindQuery
ShouldBindQuery函数只绑定 url 查询参数而忽略 post 数据
二、文件上传:
1. form表单上传单文件&&多文件:
.
├── chapter04
│ ├── file_upload.go
│ └── post.go
├── main.go
├── static
│ ├── css
│ ├── images
│ └── js
├── template
│ ├── chapter04
│ │ ├── fileUpload.html
│ │ └── user_add.html
└── upload
├── timg.jpeg
├── ttt.jpg
└── �\217\220示�\237�2.mp3
./main.go
package main
import (
"gin_project/chapter04"
"github.com/gin-gonic/gin"
)
func main() {
engine := gin.Default()
// 注册模板
engine.LoadHTMLGlob("template/**/*")
// 注册静态文件
engine.Static("./static", "static")
// 注册路由
// 文件上传
engine.GET("/to_fileUpload", chapter04.ToFileUpload)
engine.POST("/fileUpload", chapter04.FileUpload) // 表单单文件
engine.POST("/fileUploads", chapter04.FileUploads) // 表单多文件
engine.Run(":9000")
}
./chapter04/file_upload.go
package chapter04
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
func ToFileUpload(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "chapter04/fileUpload.html", nil)
}
// 接收单文件
func FileUpload(ctx *gin.Context) {
file, _ := ctx.FormFile("file") // 获取文件
fmt.Println(file.Filename)
time_unix := strconv.FormatInt(time.Now().Unix(), 10) // 获取时间戳并转成字符串
file_path := "upload/" + time_unix + file.Filename // 设置保存文件的路径,不要忘了后面的文件名
ctx.SaveUploadedFile(file, file_path) // 保存文件
ctx.String(http.StatusOK, "上传成功")
}
// 接收多文件
func FileUploads(ctx *gin.Context) {
form, _ := ctx.MultipartForm()
files := form.File["file"] // 获取文件
for _, file := range files {
fmt.Println(file.Filename)
file_path := "upload/" + file.Filename // 设置保存文件的路径,不要忘了后面的文件名
ctx.SaveUploadedFile(file, file_path) // 保存文件
}
ctx.String(http.StatusOK, "上传成功")
}
./template/chapter04/fileUpload.html
{{ define "chapter04/fileUpload.html" }}
<!DOCTYPE html>
<html lang="zh">
<head>
<title>文件上传练习</title>
<style>
.fileForm {
width: 300px;
margin: 100px auto;
}
</style>
</head>
<body>
<div class="fileForm">
<h2>上传单文件</h2>
<form action="/fileUpload" method="post" enctype="multipart/form-data">
<!-- 注意:设置enctype参数 -->
<span>文件: </span><input type="file" name="file"><br>
<input type="submit" value="提交">
</form>
</div>
<div class="fileForm">
<h2>上传多文件</h2>
<form action="/fileUploads" method="post" enctype="multipart/form-data">
<!-- 相同的name -->
<span>文件1: </span><input type="file" name="file"><br>
<span>文件2: </span><input type="file" name="file"><br>
<span>文件3: </span><input type="file" name="file"><br>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
{{ end }}
2. ajax上传单文件&&多文件:
./
├── chapter04
│ ├── file_upload.go
├── main.go
├── static
│ ├── css
│ ├── images
│ └── js
├── template
│ ├── chapter04
│ │ ├── ajaxFile.html
│ │ ├── fileUpload.html
└── upload
./main.go
package main
import (
"gin_project/chapter04"
"github.com/gin-gonic/gin"
)
func main() {
engine := gin.Default()
// 注册模板
engine.LoadHTMLGlob("template/**/*")
// 注册静态文件
engine.Static("./static", "static")
// 注册路由
engine.GET("/to_user_add", chapter04.ToUserAdd4) // 获取请求页面
engine.POST("/user_add", chapter04.PostForm4)
// 文件上传
engine.GET("/to_ajaxFileUpload", chapter04.ToAjaxFileUpload)
engine.POST("/ajaxFileUpload", chapter04.AjaxFileUpload) // ajax单文件
engine.POST("/ajaxFileUploads", chapter04.AjaxFileUploads) // ajax多文件
engine.Run(":9000")
}
./chapter04/file_upload.go
package chapter04
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
func ToAjaxFileUpload(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "chapter04/ajaxFile.html", nil)
}
func AjaxFileUpload(ctx *gin.Context) {
file, _ := ctx.FormFile("file") // 获取文件
fmt.Println(file.Filename)
time_unix := strconv.FormatInt(time.Now().Unix(), 10) // 获取时间戳并转成字符串
file_path := "upload/" + time_unix + file.Filename // 设置保存文件的路径,不要忘了后面的文件名
ctx.SaveUploadedFile(file, file_path) // 保存文件
ctx.String(http.StatusOK, "上传成功")
}
func AjaxFileUploads(ctx *gin.Context) {
form, _ := ctx.MultipartForm()
files := form.File["file"] // 获取文件
for _, file := range files {
fmt.Println(file.Filename)
file_path := "upload/" + file.Filename // 设置保存文件的路径,不要忘了后面的文件名
ctx.SaveUploadedFile(file, file_path) // 保存文件
}
ctx.String(http.StatusOK, "上传成功")
}
./template/chapter04/ajaxFile.html
{{ define "chapter04/ajaxFile.html" }}
<!DOCTYPE html>
<html lang="zh">
<head>
<title>ajax文件上传练习</title>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<style>
.fileForm {
width: 300px;
margin: 100px auto;
}
</style>
</head>
<body>
<div class="fileForm">
<h2>ajax上传单文件</h2>
<form>
<span>文件: </span><input type="file" name="file" id="file"><br>
<input type="button" id="file_btn" value="提交">
</form>
</div>
<div class="fileForm">
<h2>ajax上传多文件</h2>
<form>
<!-- 相同的name -->
<span>文件1: </span><input type="file" name="files" class="files"><br>
<span>文件2: </span><input type="file" name="files" class="files"><br>
<span>文件3: </span><input type="file" name="files" class="files"><br>
<input type="button" value="提交" id="files_btn">
</form>
</div>
<script>
// 上传单个文件
var file_btn = document.getElementById("file_btn");
file_btn.onclick = function (ev) {
var file = $("#file")[0].files[0];
var form_data = new FormData();
form_data.append("file",file);
// ajax中需要加两个参数:
// contentType:false,
// processData:false,
$.ajax({
url:"/ajaxFileUpload",
type:"POST",
data:form_data,
contentType:false,
processData:false,
success:function (data) {
alert(data);
},
fail:function (data) {
console.log(data);
}
})
}
// 上传多个文件
var files_btn = document.querySelector("#files_btn")
files_btn.onclick = function(ev) {
var files = document.querySelectorAll(".files")
console.log(files);
var form_data = new FormData();
for(let file in files) {
form_data.append("file",file);
}
$.ajax({
url:"/ajaxFileUploads",
type:"POST",
data:form_data,
contentType:false,
processData:false,
success:function (data) {
alert(data);
},
fail:function (data) {
console.log(data);
}
})
}
</script>
</body>
</html>
{{ end }}
三、其他数据格式输出:
1. JSON:
func OutJson(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"code": 200,
"tag": "<br>",
"msg": "提交成功",
"html": "<b>Hello, world!</b>",
})
// {"code":200,"html":"\u003cb\u003eHello, world!\u003c/b\u003e","msg":"提交成功","tag":"\u003cbr\u003e"}
}
2. AsciiJSON:
生成具有转义的非 ASCII 字符的 ASCII-only JSON
func OutAsciiJson(ctx *gin.Context) {
ctx.AsciiJSON(http.StatusOK, gin.H{
"code": 200,
"tag": "<br>",
"msg": "提交成功",
"html": "<b>Hello, world!</b>",
})
// {"code":200,"html":"\u003cb\u003eHello, world!\u003c/b\u003e","msg":"\u63d0\u4ea4\u6210\u529f","tag":"\u003cbr\u003e"}
}
3. JSONP:
使用 JSONP 向不同域的服务器请求数据。如果查询参数存在回调,则将回调添加到响应体中;
如果传输的数据在两个不同的域,由于在javascript里无法跨域获取数据,所以一般采取script标签的方式获取数据,传入一些callback来获取最终的数据,这就有可能造成敏感信息被劫持;
func OutJsonp(ctx *gin.Context) {
ctx.AsciiJSON(http.StatusOK, gin.H{
"code": 200,
"tag": "<br>",
"msg": "提交成功",
"html": "<b>Hello, world!</b>",
})
// {"code":200,"html":"\u003cb\u003eHello, world!\u003c/b\u003e","msg":"提交成功","tag":"\u003cbr\u003e"}
}
4. PureJSON:
func OutPureJSON(ctx *gin.Context) {
ctx.PureJSON(http.StatusOK, gin.H{
"code": 200,
"tag": "<br>",
"msg": "提交成功",
})
// {"code":200,"html":"<b>Hello, world!</b>","msg":"提交成功","tag":"<br>"}
}
5. SecureJSON
使用 SecureJSON 防止 json 劫持。如果给定的结构是数组值,则默认预置 “while(1),” 到响应体;
json劫持:利用网站的cookie未过期,然后访问了攻击者的虚假页面,那么该页面就可以拿到json形式的用户敏感信息;
func OutSecureJSON(ctx *gin.Context) {
names := []string{"lena", "austin", "foo"}
ctx.SecureJSON(http.StatusOK, names)
}
6. XML:
func OutXML(ctx *gin.Context) {
ctx.XML(http.StatusOK, gin.H{
"code": 200,
"tag": "<br>",
"msg": "提交成功",
"html": "<b>Hello, world!</b>",
})
}
7. YAML:
func OutYML(ctx *gin.Context) {
ctx.YAML(http.StatusOK, gin.H{
"code": 200,
"tag": "<br>",
"user": gin.H{"name": "zhiliao", "age": 18},
"html": "<b>Hello, world!</b>",
})
}
8.ProtoBuf:
四、自定义HTTP配置:
1.http请求补充:
router := gin.Default()
router.GET("/someGet", getting)
router.POST("/somePost", posting)
router.PUT("/somePut", putting)
router.DELETE("/someDelete", deleting)
router.PATCH("/somePatch", patching)
router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options)
2. 设置启动参数
func main() {
router := gin.Default()
...
http.ListenAndServe(":8080", router)
}
func main() {
router := gin.Default()
...
s := &http.Server{
Addr: ":8080",
Handler: router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
}
相关文章
- JQuery上传文件插件Uploadify使用笔记
- 文件上传之跨服务器上传分析和搭建环境
- structs2之多文件上传
- Linux远程连接工具:SecureCRT【编辑】、SecureFX Portable【上传文件、下载文件;不需要再配置Linux端的ftpd】
- 网站漏洞——文件判断函数的安全风险(实战篇)
- 关于finecms v5 会员头像 任意文件上传漏洞分析
- 问题:CSV数据文件处理,从TXT文件中读取数据是前面有一个点,空格
- Spring+Quartz实现文件中转站
- Spring Boot 静态资源映射与上传文件路由配置
- 文件上传change事件只执行一次的问题
- uri中为什么本地文件file后面跟三个斜杠, http等协议跟两个斜杠?
- java操作ftp实现文件上传
- 通过io,response将文件下载并返回前端
- 文件和目录(IO)操作
- php 上传大文件主要涉及配置upload_max_filesize和post_max_size两个选项
- Nginx 系列 | (转)Nginx 上传文件:client_max_body_size 、client_body_buffer_size
- 块/文件/对象存储对比性概述
- Antd Upload组件上传文件至php后端, php拿到对应的文件名
- 使用PuTTY上传文件
- java 读写文件
- Python - 生成 requirement.txt 文件
- html 文件上传框 input标签
- servlet上传文件报错(二)
- java将二维数组转为稀疏数组保存到本地并读取本地文件转为二维数组
- 【Linux 内核】Linux 内核源码根目录下的文件 ( .clang-format | COPYING | CREDITS | Kbuild | Kconfig | MAINTAINERS )
- Delphi获取文件的大小(实际&物理)
- servlet3.0获取参数与文件上传代码示例
- C语言 HTTP上传文件-利用libcurl库上传文件
- iOS_文件上传进度条的实现思路-AFNettworking
- 2019-8-31-asp-dotnet-core-支持客户端上传文件