目录
- 前言
- 使用原生net/http库实现文件上传
- 使用Gin实现文件上传
- 单个文件上传
- FormFile()获取文件
- SaveUploadedFile()保存到本地
- 设置缓冲区大小
- 限制文件大小
- 限制文件类型
- 完整示例
- 测试文件上传
- 多个文件上传
- MultipartForm()获取多个文件
- 测试文件上传
- 总结
前言
今天我们来聊聊如何使用Gin实现文件上传。
Go标准库net/http对文件上传已经提供了非常完善的支持,而Gin框架在其基础上进一步封装,因此使用Gin开发文件上传功能时,只需要简单几行代码便可以实现,Gin框架支持单个文件与多个文件同时上传。
使用原生net/http库实现文件上传
我们首先看看实现一个HTTP服务器,提供文件上传功能的简单示例
package main
import (
\”io\”
\”io/ioutil\”
\”log\”
\”net/http\”
\”github.com/julienschmidt/httprouter\”
)
const (
MAX_UPLOAD_SIZE = 1024 * 1024 * 20 //最大上传大小,50MB
)
func main() {
r := RegisterHandlers()
http.ListenAndServe(\”:8080\”, r) // 开启一个http服务
}
// 定义路由
func RegisterHandlers() *httprouter.Router {
router := httprouter.New()
router.POST(\”/upload\”, uploadHandler)
return router
}
// 文件上传接口
func uploadHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE)
if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {
log.Printf(\”File is too big\”)
return
}
file, headers, err := r.FormFile(\”file\”)
if err != nil {
log.Printf(\”Error when try to get file: %v\”, err)
return
}
//获取上传文件的类型
if headers.Header.Get(\”Content-Type\”) != \”image/png\” {
log.Printf(\”只允许上传png图片\”)
return
}
data, err := ioutil.ReadAll(file)
if err != nil {
log.Printf(\”Read file error: %v\”, err)
return
}
fn := headers.Filename
err = ioutil.WriteFile(\”./video/\”+fn, data, 0666)
if err != nil {
log.Printf(\”Write file error: %v\”, err)
return
}
w.WriteHeader(http.StatusCreated)
io.WriteString(w, \”Uploaded successfully\”)
}
如上我们通过r.FormFile函数获取上传的文件对象,以及文件的相关信息。然后通过headers.Header.Get函数获取上传文件的类型,判断类型是否符合要求。接着,使用ioutil.ReadAll函数读取文件的内容,并将其存储在data变量中。然后,通过headers.Filename获取上传文件的文件名,并使用ioutil.WriteFile函数将文件内容写入到指定路径下的文件中。
使用Gin实现文件上传
单个文件上传
FormFile()获取文件
单文件上传使用gin.Context的FormFile()方法,该方法的值为POST请求中文件上传字段的名称:
engine := gin.Default()
engine.POST(\”/upload\”, func(c *gin.Context) {
file, err := c.FormFile(\”file\”)
})
engine.Run()
SaveUploadedFile()保存到本地
调用gin.Context的SaveUploadedFile()方法可以将文件保存到某个目录下:
dst := \”./uploads/\” + file.Filename
c.SaveUploadedFile(file,\”./uploadFile\”)
设置缓冲区大小
Go默认文件上传缓冲区为32M,当有大量文件上传时,服务器内存的压力会很大,因此可以通过MaxMultipartMemory属性来设置缓冲区大小:
//8M
engine.MaxMultipartMemory = 8 << 20
限制文件大小
上传文件时,不限制文件大小可以会导致服务存储空间暴涨,因为有必须限制上传文件大小:
fileMaxSize := 4 << 20 //4M
if int(file.Size) > fileMaxSize {
c.String(http.StatusBadRequest, \”文件不允许大小于4M\”)
return
}
限制文件类型
对文件类型,也可以进行限制:
reader, err := file.Open()
if err != nil {
fmt.Println(err)
return
}
b := make([]byte, 512)
reader.Read(b)
contentType := http.DetectContentType(b)
if contentType != \”image/jpeg\” && contentType != \”image/png\” {
c.String(http.StatusOK, \”文件格式错误\”)
return
}
在上面的代码中,我们读取文件的前512个字节,再调用http.DetectContentType()便可以获取文件的MIME值。
完整示例
package main
import (
\”fmt\”
\”log\”
\”net/http\”
\”github.com/gin-gonic/gin\”
)
func main() {
engine := gin.Default()
//8M
engine.MaxMultipartMemory = 8 << 20
engine.POST(\”/upload\”, func(c *gin.Context) {
file, err := c.FormFile(\”file\”)
if err != nil {
log.Println(err)
c.String(http.StatusBadRequest, \”文件上传失败\”)
return
}
fileMaxSize := 4 << 20 //4M
if int(file.Size) > fileMaxSize {
c.String(http.StatusBadRequest, \”文件不允许大小于32KB\”)
return
}
reader, err := file.Open()
if err != nil {
fmt.Println(err)
return
}
b := make([]byte, 512)
reader.Read(b)
contentType := http.DetectContentType(b)
if contentType != \”image/jpeg\” && contentType != \”image/png\” {
c.String(http.StatusOK, \”文件格式错误\”)
return
}
dst := \”./uploads/\” + file.Filename
c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf(\”\’%s\’ 上传成功!\”, file.Filename))
})
engine.Run()
}
测试文件上传
$ curl -F \”file=@./1.jpg\” -X POST \”http://localhost:8080/upload\”
\’1.jpg\’ 上传成功!
多个文件上传
MultipartForm()获取多个文件
如果要上传多个文件,多次调用gin.Context的FormFile()方法也是可以的,但更好的方式是使用gin.Context的MultipartForm()方法:
package main
import (
\”fmt\”
\”log\”
\”net/http\”
\”github.com/gin-gonic/gin\”
)
func main() {
engine := gin.Default()
engine.POST(\”/uploadMul\”, func(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
log.Println(err)
c.String(http.StatusBadRequest, \”文件上传失败\”)
return
}
files := form.File[\”upload\”]
for _, file := range files {
fmt.Println(file.Filename)
}
c.String(http.StatusOK, fmt.Sprintf(\”%d files uploaded!\”, len(files)))
})
engine.Run()
}
测试文件上传
运行程序后,使用curl命令上传多个文件:
$ curl -F \”upload=@./1.jpg\” -F \”upload=@./2.jpg\” -X POST \”http://localhost:8080/uploadMul
2 files uploaded
总结
Go标准库net/http对文件上传已经提供了非常完善的支持,可以满足我们大部分需求,Gin框架在其基础做了封装,让我们使用起来更加方便迅速。
以上就是Golang使用Gin实现文件上传的示例代码的详细内容,更多关于Golang Gin文件上传的资料请关注悠久资源网其它相关文章!
您可能感兴趣的文章:
- Golang使用Gin处理下载文件请求返回
- Golang使用Gin框架实现HTTP上传文件过程介绍
- golang gin框架实现大文件的流式上传功能
- golang Gin上传文件返回前端及中间件实现示例
- GolangGin框架实现文件下载功能的示例代码