http.Client 读gzip内容读不全

tablecell · · 1468 次点击
jan-bar
想要拥有,必定付出。
我尝试研究了一下源码 ```go // Reader is the interface that wraps the basic Read method. // // Read reads up to len(p) bytes into p. It returns the number of bytes // read (0 <= n <= len(p)) and any error encountered. Even if Read // returns n < len(p), it may use all of p as scratch space during the call. // If some data is available but not len(p) bytes, Read conventionally // returns what is available instead of waiting for more. // // When Read encounters an error or end-of-file condition after // successfully reading n > 0 bytes, it returns the number of // bytes read. It may return the (non-nil) error from the same call // or return the error (and n == 0) from a subsequent call. // An instance of this general case is that a Reader returning // a non-zero number of bytes at the end of the input stream may // return either err == EOF or err == nil. The next Read should // return 0, EOF. // // Callers should always process the n > 0 bytes returned before // considering the error err. Doing so correctly handles I/O errors // that happen after reading some bytes and also both of the // allowed EOF behaviors. // // Implementations of Read are discouraged from returning a // zero byte count with a nil error, except when len(p) == 0. // Callers should treat a return of 0 and nil as indicating that // nothing happened; in particular it does not indicate EOF. // // Implementations must not retain p. type Reader interface { Read(p []byte) (n int, err error) } ``` 也就是说你应该在判断err之前处理部分数据,这才符合人家规定。而且我看你的错误是一个确定的返回 也可以用下面这个逻辑不处理那种错误,网上有其他人遇到解决方案也是遇到这个错误忽略就好 ```go byt, err := ioutil.ReadAll(reader) if err != nil && err != io.ErrUnexpectedEOF { fmt.Println("ioutil.ReadAll", err) return } ``` 遇到错误不能一棒子打死,得分析这是正常错误还是需要处理的错误。
#6
更多评论
io.Reader接口说明里面讲的很清楚,Read会返回n>0且err=EOF的情况,即读取最后不满buffer长度的数据场景,修改成如下即可。 ```go for { buf := make([] byte, 1024) n,err := reader.Read(buf) if n > 0 { fmt.Println(string(buf)) } if nil != err { return; } } ```
#1
jan-bar
想要拥有,必定付出。
看来楼主有些写法还在用C语言的习惯啊。不过从io.Reader里面读出全部数据还是建议使用byt, err := ioutil.ReadAll(reader) 如果坚持自己写方法的话可以参考一楼回答。我对楼主的代码做了写更改,就是把一些写法简化,去掉分号。 ```go package main import ( "compress/gzip" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://blog.csdn.net/yjp19871013/article/details/82555417" client := &http.Client{} req, err := http.NewRequest("GET", url, nil) if nil != err { return } req.Header.Add("Accept-Encoding", "gzip, deflate") resp, err := client.Do(req) if nil != err { return } defer resp.Body.Close() if 200 == resp.StatusCode { a := resp.Header for k, v := range a { fmt.Println(k, v) } fmt.Println(resp.Header.Get("Content-Encoding")) reader, err := gzip.NewReader(resp.Body) if nil != err { return } byt, err := ioutil.ReadAll(reader) if nil != err { return } fmt.Println(string(byt)) } else { fmt.Println(resp.StatusCode) } } ```
#2