为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕姐4208626 2022-06-27 16:32:16
我正在尝试发出一个简单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.Buffertee := io.TeeReader(file, &buf)ioutil.ReadAll(tee)                                 request, _ := http.NewRequest("PUT", myURL, &buf)   // this works finerequest.Header.Set("Content-Type", "application/octet-stream")http.DefaultClient.Do(request)编辑:问题不在于设置ContentLength标题(即它被设置为默认值 0);这导致服务器不处理上传。使用缓冲区时,golang确实将标头设置为缓冲区长度,从而导致不同的行为。ContentLength标头语义服务器是否依赖?浏览所以我的印象是标题是可选的,这显然不是这里的情况。
查看完整描述

1 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

此源代码可能会有所帮助。


    // /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 }

        }

    }


查看完整回答
反对 回复 2022-06-27
  • 1 回答
  • 0 关注
  • 452 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信