GoのPipeはシーンを適用し、multipartリクエストをサーバに送信する
3778 ワード
multipart
要求はマルチコンポーネント要求体であり、一般的にファイルのアップロードなどのシーンに多く用いられるが、ファイルのアップロードのため、要求体験が大きいため、メモリに完全な要求体を構築するのに適していない(例えばbytes.Buffer
を使用する).この場合、
Pipe
を使用することを考慮することができます.Writer
とReader
を返します.パイプフローは、名前の通り、頭で読んで、頭で書きます.ディスクファイルを読み込み、ネットワークに書き込み、メモリにキャッシュしません.このシーンにぴったりです.func Pipe() (*PipeReader, *PipeWriter) {
p := &pipe{
wrCh: make(chan []byte),
rdCh: make(chan int),
done: make(chan struct{}),
}
return &PipeReader{p}, &PipeWriter{p}
}
Demo
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"net/textproto"
"strings"
"time"
)
func main(){
// Http
ctx, cancel := context.WithCancel(context.Background())
ch := make(chan struct{})
go server(ctx, ch)
//
r, w := io.Pipe()
defer r.Close()
// multipart, writer
formWriter := multipart.NewWriter(w)
go func() {
defer w.Close()
var writer io.Writer
// ,key/value
formWriter.WriteField("lang", "PHP ")
// , Writer
writer, _ = formWriter.CreateFormField("lang")
writer.Write([]byte("Java "))
// , , , Writer , ContentType application/octet-stream
writer, _ = formWriter.CreateFormFile("file", "app.json")
jsonVal, _ := json.Marshal(map[string] string {"name": "KevinBlandy"})
writer.Write(jsonVal)
// part , header
header := textproto.MIMEHeader{}
header.Set("Content-Disposition", `form-data; name="file"; filename="app1.json"`) // , ,
header.Set("Content-Type", `application/octet-stream`) // ContentType,
writer, _ = formWriter.CreatePart(header)
writer.Write([]byte("foo"))
// , close
formWriter.Close()
}()
// http
client := http.Client{}
// request , body reader
req, _ := http.NewRequest(http.MethodPost, "http://127.0.0.1/upload", r)
req.Header.Set("Content-Type", formWriter.FormDataContentType()) // ContentType
//
resp, _ := client.Do(req)
defer resp.Body.Close()
//
data, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(data))
//
cancel()
//
ログ出力
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] POST /upload --> main.server.func1 (3 handlers)
-------------------
name=lang, value=PHP ,Java
-------------------
name=file, size=22, fileName=app.json, headers=map[Content-Disposition:[form-data; name="file"; filename="app.json"] Content-Type:[application/octet-stream]]
name=file, size=3, fileName=app1.json, headers=map[Content-Disposition:[form-data; name="file"; filename="app1.json"] Content-Type:[application/octet-stream]]
[GIN] 2021/01/17 - 14:00:33 | 200 | 0s | 127.0.0.1 | POST "/upload"
success
2021/01/17 14:00:34 ...