来自golang文件的HTTP PUT请求正文:上传失败而没有正确设置ContentLength

我正在尝试发出一个简单PUT的上传文件的请求。http.NewRequest接受body(作为io.Reader)。但是传递os.Fileasbody不起作用,而首先将其读入缓冲区可以解决问题:


file, _ := os.Open(filePath)


// request, _ := http.NewRequest("PUT", myURL, file)

// ^^^ why does this not work???


var buf bytes.Buffer

tee := io.TeeReader(file, &buf)

ioutil.ReadAll(tee)                                 

request, _ := http.NewRequest("PUT", myURL, &buf)   // this works fine


request.Header.Set("Content-Type", "application/octet-stream")

http.DefaultClient.Do(request)

编辑:问题不在于设置ContentLength标题(即它被设置为默认值 0);这导致服务器不处理上传。使用缓冲区时,golang确实将标头设置为缓冲区长度,从而导致不同的行为。


ContentLength标头语义服务器是否依赖?浏览所以我的印象是标题是可选的,这显然不是这里的情况。


慕姐4208626
浏览 453回答 1
1回答

肥皂起泡泡

此源代码可能会有所帮助。    // /usr/lib/go/src/net/http/request.go:872    if body != nil {        switch v := body.(type) {        case *bytes.Buffer:            req.ContentLength = int64(v.Len())            buf := v.Bytes()            req.GetBody = func() (io.ReadCloser, error) {                r := bytes.NewReader(buf)                return ioutil.NopCloser(r), nil            }        case *bytes.Reader:            req.ContentLength = int64(v.Len())            snapshot := *v            req.GetBody = func() (io.ReadCloser, error) {                r := snapshot                return ioutil.NopCloser(&r), nil            }        case *strings.Reader:            req.ContentLength = int64(v.Len())            snapshot := *v            req.GetBody = func() (io.ReadCloser, error) {                r := snapshot                return ioutil.NopCloser(&r), nil            }        default:            // This is where we'd set it to -1 (at least            // if body != NoBody) to mean unknown, but            // that broke people during the Go 1.8 testing            // period. People depend on it being 0 I            // guess. Maybe retry later. See Issue 18117.        }        // For client requests, Request.ContentLength of 0        // means either actually 0, or unknown. The only way        // to explicitly say that the ContentLength is zero is        // to set the Body to nil. But turns out too much code        // depends on NewRequest returning a non-nil Body,        // so we use a well-known ReadCloser variable instead        // and have the http package also treat that sentinel        // variable to mean explicitly zero.        if req.GetBody != nil && req.ContentLength == 0 {            req.Body = NoBody            req.GetBody = func() (io.ReadCloser, error) { return NoBody, nil }        }    }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go