http.Post()
的第三個參數允許io.Reader
,這意味着返回值os.Open()
應該工作。但是下面的代碼會得到意想不到的結果,換句話說,它不會正確設置Content-Length
。也許File
類型沒有實現。有沒有合適的方法可以用*File
來設置Content-Length
?如何使用os.Open()的返回值作爲http.Post()的第三個參數並設置Content-Length?
package main
import (
"bytes"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"os"
)
var sample = []byte(`hello`)
func main() {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println(r.Header)
if int(r.ContentLength) != len(sample) {
log.Fatal("Unexpected Content-Length:", r.ContentLength)
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{}`))
}))
defer ts.Close()
file, err := ioutil.TempFile(os.TempDir(), "")
if err != nil {
log.Fatal(err)
}
defer os.Remove(file.Name())
file.Write(sample)
// This works
buf, err := ioutil.ReadFile(file.Name())
if err != nil {
log.Fatal(err)
}
_, err = http.Post(ts.URL, "application/octet-stream", bytes.NewBuffer(buf))
if err != nil {
log.Fatal(err)
}
// This looks fine in my opinion, though it doesn't set Content-Length
f, err := os.Open(file.Name())
if err != nil {
log.Fatal(err)
}
_, err = http.Post(ts.URL, "application/octet-stream", f)
if err != nil {
log.Fatal(err)
}
}
輸出:
2009/11/10 23:00:00 map[Content-Type:[application/octet-stream] Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1] Content-Length:[5]]
2009/11/10 23:00:00 map[Content-Type:[application/octet-stream] Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
2009/11/10 23:00:00 Unexpected Content-Length:-1
https://play.golang.org/p/hJLN2H9Y9p
爲什麼你需要設置Content-Length? – JimB
使用Flask(python)構建的Web應用程序具有'request.stream',並且在發送Content-Length時不起作用。 – Nobu