1. 上传单个文件
-
multipart/form-data格式用于文件上传
-
gin文件上传与原生的net/http方法类似,不同在于gin把原生的request封装到c.Request中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</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>
在 Go 语言中,<<
是位运算符,表示按位左移操作。8 << 20
的含义是将整数 8 左移 20 位,即将二进制表示的数值 8 左移 20 位。
在这种情况下,8
的二进制表示是 0000 1000
,将其左移 20 位后,即在低位添加 20 个 0,结果为 1000 0000 0000 0000 0000 0000 0000
。
将这个二进制数转换为十进制数,即为 8388608
。因此,在 Go 中,8 << 20
的结果为 8388608
。
8 << 20
表示将整数 8 左移 20 位,结果为 8388608
。这个值代表的是字节数。要将字节数转换为兆字节(MB),可以使用以下公式:
{MB} = {字节数} /{1024* 1024}
将 8388608
字节代入公式中:
MB = 8388608 / (1024 * 1024) = 8 \text{ MB} ]
因此,在这种情况下,r.MaxMultipartMemory = 8 << 20
表示 MaxMultipartMemory
的值被设置为 8 MB
。
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
// 默认使用了两个中间件Logger(),Recovery()
r := gin.Default()
// 2.绑定路由规则,执行的函数
// gin.Context,封装了request和response
r.POST("/form", func(c *gin.Context) {
types := c.DefaultPostForm("type", "post")
username := c.PostForm("username")
pwd := c.PostForm("userpassword")
c.String(http.StatusOK, fmt.Sprintf("username: %s, pwd: %s, type: %s", username, pwd, types))
})
// 规定最大上传尺寸 8MB
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(c *gin.Context) {
file, err := c.FormFile("file") // 从请求中获取上传的文件
// 指定路径名
uploadPath := "./file/" + file.Filename
if err != nil {
c.String(500, "上传图片错误") // 如果获取文件出错,返回500 状态码 和错误信息
}
downerr := c.SaveUploadedFile(file, uploadPath) //保存上传的文件到服务器的指定路径
if downerr != nil {
// 保存文件时出错
c.String(http.StatusInternalServerError, "保存文件失败")
} else {
// 文件保存成功
c.String(http.StatusOK, "文件下载成功,保存路径为:"+uploadPath) //在上传成功后,返回状态码 200(http.StatusOK)和上传成功的文件名。
}
})
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8080")
r.Run()
}
2.上传指定文件
gin里没有专门的函数,所以需要后端把上传的文件命进行判断处理
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.MaxMultipartMemory = 8 << 20
r.POST("/upload2", func(c *gin.Context) {
_, headers, err := c.Request.FormFile("file")
if err != nil {
c.String(http.StatusOK, fmt.Sprintf(" Error when try to get file : %v", err))
}
// herders.Size 获取文件大小
if headers.Size > 1024*1024*2 {
c.String(http.StatusOK, "文件太大了")
return
}
// headers.Herder.Get("Content-Type")获取上传文件的类型
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()
}
上传正确的格式和文件大小
错误上传文件格式
报错
我重新写一遍后端的时候容易遗忘漏掉 r.Run() 函数,那么启动main.go的过程中会出现如下报错
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] POST /upload2 --> main.main.func1 (3 handlers)
养成好习惯,先写 r.Run()