MIME タイプ、application/json は見たことある程度の認識だったので他のタイプも見てみる。
開発環境
# Google Chrome バージョン: 100.0.4896.75(Official Build) (x86_64) # Go /go/src # go version go version go1.17.8 linux/amd64
multipart/form-data とは
text/plain
や image/png
などの MIME タイプの一つ。
サーバーのレスポンスで Content-Type ヘッダーとして送信する。正しく設定されていない場合、ブラウザがファイルの中身を誤って解釈してしまう恐れがある。
<form action="/users" method="post" enctype="multipart/form-data"> <div> <label>Name: </label> <input type="text" name="name" required> </div> <div> <label>File: </label> <input type="file" name="file"> </div> <div> <input type="submit"> </div> </form>
本記事では上記 HTML ファイルから生成された Web ページ上で submit した値を Go で受け取る処理を書く。
コード
package main import ( "fmt" "io" "net/http" ) func main() { http.Handle("/", http.FileServer(http.Dir("./"))) http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { mr, _ := r.MultipartReader() for { p, err := mr.NextPart() if err == io.EOF { break } // input type が "text" の場合は FileName() が空になる if len(p.FileName()) == 0 { d := make([]byte, 1024) _, _ = p.Read(d) fmt.Println(p.FormName(), ":", string(d), p.Header.Get("Content-Type")) } else { fmt.Println(p.FormName(), ":", p.FileName(), p.Header.Get("Content-Type")) } } // POST したときに localhost:8080/users にとどまってしまうのでルートにリダイレクト http.Redirect(w, r, "/", 301) }) http.ListenAndServe(":8080", nil) }
実行結果
↓
name : Yoshi
file : test.png image/png
enctype
method 属性の値が post であるとき、この属性はフォームをサーバーに送信する際に使用する、コンテンツの MIME タイプを示します。以下の値が指定可能です。
form - HTML: HyperText Markup Language | MDN
form タグの属性 enctype をmultipart/form-data に設定しなかった場合、Go 側でのレスポンスには application/x-www-form-urlencoded が格納される。MultipartReader()は使用できないので enctype を設定しておく。