Mastering Form Handling and File Uploads with Gin in Go
This guide explains the four common HTTP form content types, demonstrates how to retrieve form data with Gin's PostForm methods, shows step‑by‑step examples for single and multiple file uploads, enforces size and type restrictions, and covers route groups and custom 404 handling in Go.
Form Parameters
Form data is sent via POST requests using four typical content types: application/json, application/x-www-form-urlencoded, application/xml, and multipart/form-data. Gin's PostForm() method parses x-www-form-urlencoded and multipart/form-data by default.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Example</title>
</head>
<body>
<form action="http://localhost:8080/form" method="post" enctype="application/x-www-form-urlencoded">
用户名:<input type="text" name="username" placeholder="请输入你的用户名"> <br>
密码:<input type="password" name="userpassword" placeholder="请输入你的密码"> <br>
<input type="submit" value="提交">
</form>
</body>
</html> package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.POST("/form", func(ctx *gin.Context) {
types := ctx.DefaultPostForm("type", "post")
username := ctx.PostForm("username")
password := ctx.PostForm("userpassword")
ctx.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))
})
r.Run()
}File Upload
The multipart/form-data format is used for uploading files. Gin wraps the native net/http request, exposing file handling through the context.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload</title>
</head>
<body>
<form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
上传文件: <input type="file" name="file">
<input type="submit" value="提交">
</form>
</body>
</html> package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// Limit upload size to 8 MB (default is 32 MB)
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(ctx *gin.Context) {
file, err := ctx.FormFile("file")
if err != nil {
ctx.String(500, "上传图片出错")
return
}
// Save the uploaded file
ctx.SaveUploadedFile(file, file.Filename)
ctx.String(http.StatusOK, file.Filename)
})
r.Run()
}Restrict Size and Type
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.POST("/upload", func(c *gin.Context) {
_, headers, err := c.Request.FormFile("file")
if err != nil {
log.Printf("Error when try to get file: %v", err)
return
}
// Limit size to 2 MB
if headers.Size > 1024*1024*2 {
fmt.Println("文件太大了")
return
}
// Allow only PNG images
if headers.Header.Get("Content-Type") != "image/png" {
fmt.Println("只允许上传png图片")
return
}
c.SaveUploadedFile(headers, "./video/"+headers.Filename)
c.String(http.StatusOK, headers.Filename)
})
r.Run()
}Upload Multiple Files
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"fmt"
)
func main() {
r := gin.Default()
// Limit form size to 8 MB
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))
return
}
files := form.File["files"]
for _, file := range files {
if err := c.SaveUploadedFile(file, file.Filename); err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))
return
}
}
c.String(200, fmt.Sprintf("upload ok %d files", len(files)))
})
r.Run(":8000")
}Route Groups
Route groups help organize URLs with common prefixes.
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func login(ctx *gin.Context) {
name := ctx.DefaultQuery("name", "yangchao")
ctx.String(200, fmt.Sprintf("hello %s
", name))
}
func submit(ctx *gin.Context) {
name := ctx.DefaultQuery("name", "hcie")
ctx.String(200, fmt.Sprintf("hello %s
", name))
}
func main() {
r := gin.Default()
v1 := r.Group("/v1")
{
v1.GET("/login", login)
v1.GET("/submit", submit)
}
v2 := r.Group("/v2")
{
v2.POST("/login", login)
v2.POST("/submit", submit)
}
r.Run()
}Custom 404 Page
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/user", func(ctx *gin.Context) {
name := ctx.DefaultQuery("name", "yangchao")
ctx.String(http.StatusOK, fmt.Sprintf("hello %s", name))
})
// Define custom 404 handler
r.NoRoute(func(ctx *gin.Context) {
ctx.String(http.StatusNotFound, "404 no found 1123131")
})
r.Run()
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
