使用HttpWebResponse流实例化StreamReader失败:Stream不可读
解决HttpWebResponse读取分块压缩响应时的“Stream was not readable”问题
嘿,我之前也碰到过一模一样的问题!咱们先拆解下问题根源,再一步步修复代码。
首先,你代码里设置了request.Headers.Add("Accept-Encoding", "gzip, deflate"),这意味着服务器会返回压缩后的响应流(gzip或deflate格式),但你直接用StreamReader去读这个原始流,肯定会出错——因为压缩流不是可读的文本流,这就是你看到System.ArgumentException: Stream was not readable的原因。另外,分块响应的处理其实不需要你手动操作,压缩流会自动帮你处理分块的拼接。
修复步骤
- 判断响应的压缩格式:从
HttpWebResponse的ContentEncoding属性获取服务器实际返回的压缩类型。 - 用压缩流包装响应流:根据压缩类型,分别使用
GZipStream或DeflateStream来解压流。 - 通过解压后的流读取文本:把解压后的流传给
StreamReader,就能正常读取完整响应了。
修改后的完整代码
using System.IO.Compression; // 记得添加这个命名空间 public bool Login() { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://WEBSITE-REMOVED/CheckAccess"); request.CookieContainer = CookieContainer; //Set POST data. string postData = "institution=AAA"; postData += "&ismobile=false"; postData += "&id=BBB"; postData += "&password=CCC"; byte[] data = Encoding.ASCII.GetBytes(postData); //Configure HTTP POST request. request.Headers.Clear(); request.Method = "POST"; request.Accept = @"text/html, application/xhtml+xml, image/jxr, */*"; request.Referer = @"http://WEBSITE-REMOVED/entry.html"; request.Headers.Add("Accept-Language", "en-US"); request.UserAgent = @"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"; request.ContentType = @"application/x-www-form-urlencoded"; request.Headers.Add("Accept-Encoding", "gzip, deflate"); request.Host = "op.responsive.net"; request.ContentLength = data.Length; request.KeepAlive = true; request.Headers.Add("Cache-Control", "no-cache"); using (Stream stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { Stream responseStream = response.GetResponseStream(); // 处理压缩流 if (response.ContentEncoding.Equals("gzip", StringComparison.OrdinalIgnoreCase)) { responseStream = new GZipStream(responseStream, CompressionMode.Decompress); } else if (response.ContentEncoding.Equals("deflate", StringComparison.OrdinalIgnoreCase)) { responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); } // 现在可以正常读取完整响应了 using (StreamReader sr = new StreamReader(responseStream, Encoding.UTF8)) { string fullResponse = sr.ReadToEnd(); // 这里可以处理返回的响应内容,比如判断登录是否成功 // TO-DO: 逻辑处理 } } } catch(Exception ex) { File.AppendAllText(ErrorLogDirectory + "Errors.txt", "Login() Exception\r\n" + System.DateTime.Now + "\r\n" + ex.ToString() + Environment.NewLine); } return false; }
额外注意点
- 必须引用
System.IO.Compression命名空间,否则GZipStream和DeflateStream会报找不到类型的错误。 sr.ReadToEnd()会一次性读取所有分块响应的内容,不需要手动处理分块拼接逻辑。- 所有流都用
using块包裹,确保资源自动释放,避免流泄漏问题。
这样修改后,你应该就能正常读取到完整的响应内容,不会再碰到流不可读的错误了!
内容的提问来源于stack exchange,提问作者Foxslaughter
相关产品推荐
相关产品推荐

