Loading

Gin文件上传

Gin官方

官方给出了单文件与多文件的上传方式,也就是其实gin自己就实现了文件上传的功能,只不过看下来好像只能上传到本地,转发到别的服务器的话需要自己再加一些实现,并不是很难。

单文件

参考 issue #774 和详细示例代码.

func main() {
	router := gin.Default()
	// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
	router.MaxMultipartMemory = 8 << 20  // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
		// 单文件
		file, _ := c.FormFile("file")
		log.Println(file.Filename)

		dst := "./" + file.Filename
		// 上传文件至指定的完整文件路径
		c.SaveUploadedFile(file, dst)

		c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
	})
	router.Run(":8080")
}

多文件

查看详细示例代码.

func main() {
	router := gin.Default()
	// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
	router.MaxMultipartMemory = 8 << 20  // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
		// Multipart form
		form, _ := c.MultipartForm()
		files := form.File["upload[]"]

		for _, file := range files {
			log.Println(file.Filename)

			// 上传文件至指定目录
			c.SaveUploadedFile(file, dst)
		}
		c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
	})
	router.Run(":8080")
}

Gin的文件上传相关的其他特性

限制文件大小

Gin 除了提供上面的文件上传功能,还有提供限制文件上传大小的功能,这个在实际项目中会有较大的用途。

router := gin.Default()
router.MaxMultipartMemory = 8 << 20

使用 MaxMultipartMemory 来配置文件上传的大小限制,默认是32M。

文件下载服务

虽然 go 默认提供了文件服务,但是默认的文件服务会把整个文件夹下所有的文件都暴露,如果我们想做更多的控制就不太方便了,而 Gin 提供了文件下载的服务

func main() {
    router := gin.Default()

    router.GET("/local/file", func(c *gin.Context) {
        c.File("local/file.go")
    })
}

Gin 提供的文件服务,可以让我们非常方便的进行控制,甚至是动态文件,比默认的有更多的定制化玩法

大文件上传

这个是我从网上找'Gin 大文件传输'的时候,在一个论坛中找到的。网上大部分是前后端联调,协商一个分片,用来分片传输大数据参考链接。然而论坛中说到:

其实完全不需要担心,net/http 在 readForm 的时候如果文件超过指定的最大内存占用,会自动写入临时文件,所以根本不会占用太多内存

https://github.com/golang/go/blob/master/src/mime/multipart/formdata.go#L91

我去查看了Gin读取文件相关的源码,发现底层确实就是调用readForm。也就是说完全不存在大文件撑爆内存的情况。

顺便去查看了一系列的Gin关于读取http.Request的实现的博客,对于Request的读取是这么说的:

我们可以知道该函数会将请求体中的数据解析为 multipart/form-data,并且请求体中数据最大为 maxMemory 个字节,还说文件部分存储于内存中,另外部分存储于磁盘中,不过这些都与我们的 URL 编码表单无关,唯一有关的,只是简单的一句,如果需要会调用 ParseForm

也就是Gin原生读取方式就可以支持大文件传输,并且前端并不需要做分片,以form的方式提交即可

网上的选择

自定义分片上传

需要前后端协商一个分片,用来分片传输大数据

具体的做法是前端将上传的文件进行分片,并给每个文件进行标号,之后分片发送Post。后端收到请求后进行校验与拼接。

参考链接

书栈网的实现

观察书栈网的源码实现发现,他就是使用的Gin的原生FormFile读取,之后通过io.Copy保存。也就是Gin官方的做法。

总结

个人认为Gin已经把文件上传这部分做的很优秀了,如果没有更好的实现方式应该就会采用Gin原生文件上传方式。不过还是需要取舍存储在本地还是需要存储在云服务上。

posted @ 2023-02-21 17:01  ViKyanite  阅读(1145)  评论(0编辑  收藏  举报