1. 程式人生 > >golang解析http multipart/form的三種方式

golang解析http multipart/form的三種方式

iou 進行 sub family get pan ret for tro

multipart/form-data 顧名思義可以上傳多個form-data 並且用分隔符進行分割,多用於文件上傳

1. http multipart/form-data 請求樣例

POST /handle HTTP/1.1

Host: localhost:8080

Connection: keep-alive

Content-Length: 182537

Cache-Control: max-age=0

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWdDAe6hxfa4nl2Ig

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.9


------WebKitFormBoundaryWdDAe6hxfa4nl2Ig

Content-Disposition: form-data; name="submit-name"

jack

------WebKitFormBoundaryWdDAe6hxfa4nl2Ig

Content-Disposition: form-data; name="file1"; filename="out.png"

Content-Type: image/png

binary-data

------WebKitFormBoundaryWdDAe6hxfa4nl2Ig

Content-Disposition: form-data; name="file2"; filename="2.png"

Content-Type: image/png

binary-data-2

------WebKitFormBoundaryWdDAe6hxfa4nl2Ig--


2. golang解析示例


package main


import (

"bytes"

"net/http"

"io/ioutil"

"fmt"

"mime/multipart"

"io"

)


func main() {


bodyBuf := bytes.NewBuffer(nil)

bodyBuf.WriteString(`------WebKitFormBoundaryWdDAe6hxfa4nl2Ig

Content-Disposition: form-data; name="submit-name"


xiongwei

------WebKitFormBoundaryWdDAe6hxfa4nl2Ig

Content-Disposition: form-data; name="file1"; filename="out.png"

Content-Type: image/png


binary-data

------WebKitFormBoundaryWdDAe6hxfa4nl2Ig

Content-Disposition: form-data; name="file2"; filename="2.png"

Content-Type: image/png


binary-data-2

------WebKitFormBoundaryWdDAe6hxfa4nl2Ig--`)

req := &http.Request{

Method: "POST",

Header: http.Header{"Content-Type": {`multipart/form-data; boundary=----WebKitFormBoundaryWdDAe6hxfa4nl2Ig`}},

Body: ioutil.NopCloser(bodyBuf),

}


getMultiPart3(req)

}


//通過r.ParseMultipartForm

func getMultiPart1(r *http.Request) {

/**

底層通過調用multipartReader.ReadForm來解析

如果文件大小超過maxMemory,則使用臨時文件來存儲multipart/form中文件數據

*/

r.ParseMultipartForm(128)

fmt.Println("r.Form: ",r.Form)

fmt.Println("r.PostForm: ",r.PostForm)

fmt.Println("r.MultiPartForm:",r.MultipartForm)

getFormData(r.MultipartForm)


}


//通過MultipartReader

func getMultiPart2(r *http.Request)() {


mr,err := r.MultipartReader()

if err != nil{

fmt.Println("r.MultipartReader() err,",err)

return

}

form ,_ := mr.ReadForm(128)

getFormData(form)

}



//字節解析multi-part

func getMultiPart3(r *http.Request)() {


mr,err := r.MultipartReader()

if err != nil{

fmt.Println("r.MultipartReader() err,",err)

return

}

for{

p ,err := mr.NextPart()

if err == io.EOF{

break

}

if err != nil{

fmt.Println("mr.NextPart() err,",err)

break

}

fmt.Println("part header:",p.Header)

formName := p.FormName()

fileName := p.FileName()

if formName != "" && fileName == ""{

formValue,_:= ioutil.ReadAll(p)

fmt.Printf("formName:%s,formValue:%s\n",formName,formValue)

}

if fileName != "" {

fileData,_:=ioutil.ReadAll(p)

fmt.Printf("fileName:%s,fileData:%s\n",fileName,fileData)

}

fmt.Println()

}

}



func getFormData(form *multipart.Form) {

//獲取 multi-part/form body中的form value

for k,v := range form.Value{

fmt.Println("value,k,v = ",k,",",v)

}

fmt.Println()

//獲取 multi-part/form中的文件數據

for _,v := range form.File {

for i:=0 ;i < len(v);i++{

fmt.Println("file part ",i,"-->")

fmt.Println("fileName :",v[i].Filename)

fmt.Println("part-header:",v[i].Header)

f,_ := v[i].Open()

buf,_:= ioutil.ReadAll(f)

fmt.Println("file-content",string(buf))

fmt.Println()

}

}

}

技術分享圖片

golang解析http multipart/form的三種方式