编程初学者的Go语言学习之旅 | 青训营笔记

103 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第13天。

前言

昨天讲了HTTP协议有关的一些东西,今天来说说一个比较特殊的接口————投稿接口。

特殊之处

我们可以看到投稿接口的请求参数是一个Body参数,并且我们可以看到body的类型是multipart/form-dataBody参数是只有POST请求方法可以传递的,最终放到了data字段上。而multipart/form-data,表示以表单形式提交,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。
我们可以看到投稿接口的body参数中就包含一个file类型。那么,在代码中,我们应该如何处理这样的请求参数?

hertz处理body参数

在hertz框架的app包中,我们可以使用MultipartForm方法来提取body参数的表单。

func Funcname(ctx context.Context, c *app.RequestContext)  {
   form, err := c.MultipartForm()

随后我们可以使用Value方法来提取表单中的数据,以此接口为例:

token :=form.Value["token"][0]
title := form.Value["title"][0]

值得注意的是,此处的的map并不一定是键值一对一的,所以我们需要在后面加上角标来确定我们使用键值提取的是对应的哪一个参数。
而可以看到body参数中还有一个比较特殊的类型,我们可以使用File方法将此处的File数据提取出来:

file := form.File["data"]

此处的file是一个[]*multipart.FileHeader类型。

如何处理file数据?

借助app包中的Open方法,我们打开一个io流:

opened, err := file[0].Open()

随后,我们可以将流中的数据读到一个byte切片中:

var data = make([]byte, file[0].Size)//调用Size方法提前分配切片空间,提升性能
ReadSize, err := opened.Read(data)

此处我们可以对err进行简单的错误处理:

if err != nil {
   //返回错误响应
   return
}

随后,我们需要对ReadSize做错误处理,防止文件数据没有完全读入data切片:

if ReadSize != int(file[0].Size) {
   //返回错误响应
   return
}

然后使用path包指定好文件路径之后,使用OS包的WriteFile方法即可将文件数据保存在本地。