網頁

2022/6/12

Golang Web接收表單資料及檔案

Go HTTP Web接收HTML表單上傳的資料及上傳檔案。


範例環境:

  • Go 1.18

表單

建立下面HTML表單來提交資料。因為要上傳檔案所以<form>enctype屬性設為multipart/form-data

demo.html

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <form action="http://localhost:8080/employee" method="POST" enctype="multipart/form-data">
        name:<input name="name" type="text" value="John"><br>
        email:<input name="email" type="email" value="john@abc.com"><br>
        age:<input name="age" type="number" value="33"><br>
        birthday:<input name="birthday" type="date" value="1989-04-12"><br>
        gender:
            <label><input type="radio" name="gender" value="male" checked>male</label>
            <label><input type="radio" name="gender" value="female">female</label>
            <label><input type="radio" name="gender" value="others">others</label>
        <br>
        languages:
            <label><input type="checkbox" name="lang" value="en">english</label>
            <label><input type="checkbox" name="lang" value="ch" checked>mandarin</label>
            <label><input type="checkbox" name="lang" value="jp" checked>japanese</label>
        <br>
        photo:<input name="photo" type="file"><br>
        <input type="submit">
    </form>
</body>
</html>


取得表單資料

下面建立一個POST|/employee API接收從表單上傳的檔案。要先調用http.Requset.ParseMultipartForm()才能從http.Request.Form以欄位名取得表單資料及以http.Request.FormFile取得檔案。然後將取得檔案存放在專案根目錄下。

http.Requset.ParseMultipartForm()輸入參數為記憶體大小,即暫存表單及檔案的空間大小,這邊1 << 20(位移運算)相當於二進制的100000000000000000000,為2的20次方(220),也就是1024x1024,也就是1MB。

main.go

package main

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

func main() {
    http.HandleFunc("/employee", func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodPost:
            r.ParseMultipartForm(1 << 20) // 1MB

            name := r.Form.Get("name")
            email := r.Form.Get("email")
            age := r.Form.Get("age")
            birthday := r.Form.Get("birthday")
            gender := r.Form.Get("gender")
            langs := r.Form["lang"]

            file, header, err := r.FormFile("photo")
            if err != nil {
                panic(err)
            }
            defer file.Close()

            buf := bytes.NewBuffer(nil)
            _, err = io.Copy(buf, file)
            if err != nil {
                panic(err)
            }
            filename := header.Filename
            err = ioutil.WriteFile(filename, buf.Bytes(), 0666)
            if err != nil {
                panic(err)
            }

            fmt.Fprint(w, fmt.Sprintf(
                "name=%v\nemail=%v\nage=%v\nbirtyday=%v\ngender=%v\nlanguages=%v\nphoto=%v",
                name, email, age, birthday, gender, langs, filename))
        default:
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })

    http.ListenAndServe(":8080", nil)
}

github


測試

啟動專案,在瀏覽器輸入資料如下,並上傳一個gopher.jpg

name:
email:
age:
birthday:
gender:
languages:
photo:

點選Submit提交結果如下。




或用curl發送表單請求如下。

curl -X POST "http://localhost:8080/employee" -H 'content-type: multipart/form-data' -F 'name=John' -F 'email=john@abc.com' -F 'age=33' -F 'birthday=1989-04-12' -F 'gender=male' -F 'lang=en,ch,jp' -F 'photo=@./gopher.jpg'

content-type設為multipart/form-data;欄位使用-F '<name>=<value>'輸入;上傳檔案使用-F '<name>=@<filepath>'<name>為input名稱,範例為filefilepath為上傳檔案的目錄位置,範例為執行curl同目錄下的gopher.jpg

$ curl -X POST "http://localhost:8080/employee" \
> -H 'content-type: multipart/form-data' \
> -F 'name=John' \
> -F 'email=john@abc.com' \
> -F 'age=33' \
> -F 'birthday=1989-04-12' \
> -F 'gender=male' \
> -F 'lang=en,ch,jp' \
> -F 'photo=@./gopher.jpg'

回應結果。

name=John
email=john@abc.com
age=33
birtyday=1989-04-12
gender=male
languages=[en,ch,jp]
photo=gopher.jpg



沒有留言:

張貼留言