需要在上传文件的 form 表单中加入 enctype=“multipart/form-data” 属性
form 表单
{{ define "admin/useradd.html" }}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h2>演示文件上传h2>
<form action="/admin/user/doUpload" method="post" enctype="multipart/form-data">
用户名 <input type="text" name="username"><br><br>
头 像 <input type="file" name="file"><br><br>
<input type="submit" value="提交">
form>
body>
html>
{{ end }}
main.go
func main {
r := gin.Default()
// 配置模板的文件
r.LoadHTMLGlob("templates/**/*")
// 配置静态web目录 第一个参数表示路由,第二个参数表示映射的路径.
r.Static("/static", "./static")
router.POST("/admin/user/doUpload", func(c *gin.Context) {
username := c.PostForm("username")
file, err := c.FormFile("file")
// file.Filename 获取文件名称 aaa.jpg ./static/upload/aaa.jpg
dst := path.Join("./static/upload", file.Filename)
if err == nil {
c.SaveUploadedFile(file, dst)
}
c.JSON(200, gin.H{
"success": true,
"username": username,
"dst": dst,
})
}
r.Run()
}
多文件上传同单文件上传,在处理请求的时候需要一个文件一个文件的处理。
form 表单
{{ define "admin/user/add.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>Documenttitle>
head>
<body>
<form action="/admin/user/doAdd" method="post" enctype="multipart/form-data">
用户名: <input type="text" name="username" placeholder="用户名"> <br> <br>
头 像 1:<input type="file" name="face[]"><br> <br>
头 像 2:<input type="file" name="face[]"><br> <br>
<input type="submit" value="提交">
form>
body>
html>
{{ end }}
main.go
func main() {
r := gin.Default()
// 配置模板的文件
r.LoadHTMLGlob("templates/**/*")
// 配置静态web目录 第一个参数表示路由,第二个参数表示映射的路径.
r.Static("/static", "./static")
r.POST("/upload", func(c *gin.Context) {
// Multipart form
form, _ := c.MultipartForm()
files := form.File["upload[]"]
for _, file := range files {
dst := path.Join("./static/upload", file.Filename)
// 上传文件至指定目录
c.SaveUploadedFile(file, dst)
}
ctx.JSON(http.StatusOK, gin.H{
"message": "文件上传成功",
"username": username,
}
})
r.Run()
}
form 表单
{{ define "test/add.html"}}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
用户名 <input name="username" type="text"><br><br>
头 像 <input name="file" type="file"><br><br>
<input type="submit" value="提交">
form>
body>
html>
{{ end }}
业务逻辑
package main
import (
"Gin_demo/models"
"Gin_demo/routes"
"fmt"
"github.com/gin-gonic/gin"
"html/template"
"os"
"path"
"strconv"
"time"
)
// UnixToTime 时间戳转换成日期
func UnixToTime(timestamp int) string {
t := time.Unix(int64(timestamp), 0)
return t.Format("2006-01-02 15:04:05")
}
func main() {
//gin.DisableConsoleColor()
r := gin.Default()
// 自定义模板函数 , 注意要把这个函数放在加载模板前
r.SetFuncMap(template.FuncMap{
"UnixToTime": UnixToTime,
})
// 配置模板的文件
r.LoadHTMLGlob("templates/**/*")
// 配置静态web目录 第一个参数表示路由,第二个参数表示映射的路径.
r.Static("/static", "./static")
r.GET("/toUpload", func(c *gin.Context) {
c.HTML(200, "test/add.html", gin.H{})
})
r.POST("/upload", func(c *gin.Context) {
username := c.PostForm("username")
// 1、获取上层的文件
file, err := c.FormFile("file")
if err == nil {
// 2、获取文件的后缀名 判断类型是否正确
extName := path.Ext(file.Filename)
allowExtMap := map[string]bool{
".jpg": true,
".png": true,
".gif": true,
".jpeg": true,
}
_, b := allowExtMap[extName]
if !b {
c.String(200, "上传的文件类型不合法")
return
}
// 3、创建图片保存目录 static/upload/...
day := models.GetDay()
dir := "./static/upload/" + day
// 如果当前目录不存在的话,一次会创建多层
err := os.MkdirAll(dir, 0666)
if err != nil {
fmt.Println("err==>", err)
c.String(200, "MkdirAll失败")
return
}
// 4、生成文件名称和文件保存的目录
fileName := strconv.FormatInt(models.GetUnix(), 10) + extName
// 5、执行上传
dst := path.Join(dir, fileName)
c.SaveUploadedFile(file, dst)
}
c.JSON(200, gin.H{
"success": true,
"username": username,
})
})
r.Run()
}
models 文件夹当中的 utils.go
package models
import "time"
// UnixToTime 时间戳转换成日期
func UnixToTime(timestamp int) string {
t := time.Unix(int64(timestamp), 0)
return t.Format("2006-01-02 15:04:05")
}
// DateToUnix 日期转换成时间戳
func DateToUnix(str string) int64 {
template := "2006-01-02 15:04:05"
t, err := time.ParseInLocation(template, str, time.Local)
if err != nil {
return 0
}
return t.Unix()
}
// GetUnix 获取时间戳
func GetUnix() int64 {
return time.Now().Unix()
}
// GetDate 获取当前的日期
func GetDate() string {
template := "2006-01-02 15:04:05"
return time.Now().Format(template)
}
// GetDay 获取年月日
func GetDay() string {
template := "20060102"
return time.Now().Format(template)
}