likes
comments
collection
share

Go Request的Form、PostForm、MultipartForm、FormValue()、FormPostValue()、FileValue()区别

作者站长头像
站长
· 阅读数 31

大家平时可能会使用HTML的Form(表单)上传数据,特别是在上传二进制资源的时候(比如图片,视频等)。而我们一般会使用Form的两种内容格式(Content-Type),第一种是我们现在使用的比较多的multipart/form-data(一般用来上传静态资源),还有一种是application/x-www-form-urlencoded(和URL里的Query参数差不多)。这篇文章主要介绍一下这两种格式,还有在Go语言里面如何使用http.Request对象操作这两种数据格式(有许多细微的差别)。

两种Form格式

application/x-www-form-urlencoded

根据这种格式的名字,我们可以推断出来它是使用URL的编码的,当然我们也可以通过指定Accept-Charset自定Form的编码规则。它只能接收简单结构的文本数据(无法像JSON一样多层嵌套),因此现在一般都使用application/json格式代替它,下面是这种格式一个简单的例子:

/test1直接打印出Body里面的内容,而/test2则打印出Go各个application/x-www-form-urlencoded类型操作的结果

package main

import (
   "fmt"
   "io"
   "net/http"
)

func main() {
   mux := http.NewServeMux()
   mux.HandleFunc("/test1", func(w http.ResponseWriter, r *http.Request) {
      body, err := io.ReadAll(r.Body)
      defer r.Body.Close()
      if err != nil {
         return
      }
      fmt.Println(string(body))
   })
   mux.HandleFunc("/test2", func(w http.ResponseWriter, r *http.Request) {
      if err := r.ParseForm(); err != nil {
         return
      }
      fmt.Println("Form:               ", r.Form)
      fmt.Println("PostForm:           ", r.PostForm)
      fmt.Println("FormValue(name):    ", r.FormValue("name"))
      fmt.Println("FormValue(age):     ", r.FormValue("age"))
      fmt.Println("PostFormValue(name):", r.PostFormValue("name"))
      fmt.Println("PostFormValue(age): ", r.PostFormValue("age"))
   })
   server := &http.Server{
      Addr:    "127.0.0.1:8080",
      Handler: mux,
   }
   server.ListenAndServe()
}

请求格式如下:

Go Request的Form、PostForm、MultipartForm、FormValue()、FormPostValue()、FileValue()区别

在使用test1时打印:可以看到,它就是对表格编码成URL的格式,所以它可以说是Body形式的Query参数

Go Request的Form、PostForm、MultipartForm、FormValue()、FormPostValue()、FileValue()区别

在使用test2时打印:可以看到Form会包含Body里面的和URL里面的,而PostForm只包含Body里面的内容,FormValue()会读取Body和URL里面的内容,而PostFormValue()只会读取Body里面的内容。

Go Request的Form、PostForm、MultipartForm、FormValue()、FormPostValue()、FileValue()区别

multipart/form-data

这个类型是我们目前经常使用的类型,它一般会被用来上传图片,视频等内容,而它的编码方式会为资源指定类型和文件名等内容,相对于application/x-www-form-urlencoded它的编码效率更低(因为它需要更多的字符表示不同类型的数据),但是它可以支持图片,视频等二进制格式内容,一般推荐在上传静态资源的时候使用它,下面是一个简单的例子:

同上面,/test1直接打印出Body里面的内容,而/test2则打印出Go各个multipart/form-data类型操作的结果

package main

import (
   "fmt"
   "io"
   "net/http"
)

func main() {
   mux := http.NewServeMux()
   mux.HandleFunc("/test1", func(w http.ResponseWriter, r *http.Request) {
      body, err := io.ReadAll(r.Body)
      defer r.Body.Close()
      if err != nil {
         return
      }
      fmt.Println(string(body))
   })
   mux.HandleFunc("/test2", func(w http.ResponseWriter, r *http.Request) {
      if err := r.ParseMultipartForm(1024); err != nil {
         return
      }
      fmt.Println("Form:               ", r.Form)
      fmt.Println("PostForm:           ", r.PostForm)
      fmt.Println("FormValue(name):    ", r.FormValue("name"))
      fmt.Println("FormValue(age):     ", r.FormValue("age"))
      fmt.Println("PostFormValue(name):", r.PostFormValue("name"))
      fmt.Println("PostFormValue(age): ", r.PostFormValue("age"))

      fmt.Println("MultipartForm:      ", r.MultipartForm)
      file, header, err := r.FormFile("avatar")
      fmt.Println("FormFile(avatar):   ", file, header, err)
   })
   server := &http.Server{
      Addr:    "127.0.0.1:8080",
      Handler: mux,
   }
   server.ListenAndServe()
}

请求格式如下:

Go Request的Form、PostForm、MultipartForm、FormValue()、FormPostValue()、FileValue()区别

在使用test1时打印:可以看到是一种比较不节省空间的编码方式,通过----------------------------965042754073201157943416间隔每个字段,然后在下面一行Content-Disposition: form-data; name="age"中的form-data是multipart/form-data格式固定的,而name="age"表示字段名,对于二进制文件还会使用filename="381056168614065362.png"表示原始文件名(这样我们才能在服务器的接口拿到原始文件名)。对于文本字段,隔一行然后就是文本内容;对于二进制文件,隔一行然后是二进制内容。

Go Request的Form、PostForm、MultipartForm、FormValue()、FormPostValue()、FileValue()区别

在使用test2时打印:可以看到,适用于application/x-www-form-urlencoded的Go语言Request的操作也适用于multipart/form-data类型(所以multipart/form-data可以看作是支持二进制类型的application/x-www-form-urlencoded),而MultipartForm本身和PostForm一样只读取Body里面的内容,但是MultipartForm还会读取二进制的字段。而FormFile()就很明显只是获取Body里文件类型的内容。

Go Request的Form、PostForm、MultipartForm、FormValue()、FormPostValue()、FileValue()区别

总结

Go语言操作解析操作读取URL读取Body(表单)支持文本支持二进制
FormParseForm()
PostFormParseForm()
FormValue()自动调用ParseForm()
PostFormValue()自动调用ParseForm()
MultipartFormParseMultipartForm()
FormFile()自动调用ParseMultipartForm
转载自:https://juejin.cn/post/7041166794941267998
评论
请登录