Go で multipart/form-data にて POST された値を受け取る

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/plainimage/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)
}

実行結果

f:id:tokizuoh:20220412035315p:plain
localhost:8080

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 を設定しておく。

リポジトリ

github.com

参考