近段时间去了一家新公司任职,公司产品是一个网站,但是我发现它不兼容谷歌浏览器,用习惯了chrome的我简直是如鲠在喉。终于我抽出了时间,想纠正这个问题。F12一看,发现谷歌提示:net::ERR_INCOMPLETE_CHUNKED_ENCODING,跟了一下代码,发现在一个 ajax 的时候出的问题,再次跟到后台发现了一个老员工写的函数 ReturnString():
protected new void ReturnString(string str) { try { Response.Clear(); Response.Write(str); Response.Flush(); Response.Close(); } catch { } }
然后错误就出在 Response.Close() 这儿,我以前很少用 Close()都是 End(),所以也没咋注意,我简单的把 Response.Flush(); Response.Close() 改成 Response.End() 之后,暂时解决了问题,也就没管它了。
结果昨天下午,同事说另一个地方的另一个功能出了问题,他们会重复调几次后台,而第一次成功会直接 Close 掉,以拒绝掉多次调用,但 Response.End() 达不到这效果。这就是我解决了一个“BUG”,导致的另一个“BUG”。
因为快要下班了,只好先将就改回 Response.Close(),对于我这样的强迫症患者来说,这是不可忍受的。
今天一大早就过来了,百度了半天,都文不对题,要么就建议用回 Response.End,问题是我只想解决问题,不想制造新问题,这个方案当然不行。
然后研究了一会儿,抓包一看,发现数据并不完整,想到会不会是网络连接异常中断导致缓冲未完全导出,然后忽然想到之前做过一个日志记录,其中有一段用了 StreamWriter sw = new...; sw.write(string); sw.close(), 然后打开文件一看,发现 string 并未写全,12345 只写入了 123,后来改用 binarywriter 解决了问题,于是把代码一变终于解决了问题。
protected new void ReturnString(string str) { try { Response.Clear(); /* * 说明: * Response.Close() 会强制关闭客户端连接,会导致谷歌浏览器认为异常结束 * 而 Response.Write(string) 又会存在缓冲问题,在 Close 的时候,谷歌浏览器并未获取到完整的 string 内容, * 即便加上 Content-Length 参数也不管用。 * 直接 将内容转换为 byte[] 数组用 Response.BinaryWrite 可避免系统缓冲,解决此问题。 * 类似的问题也发现在 System.IO 的 StreamWriter 中,有时候写大文件的过程中 * 调用了 StreamWriter.Close() 会导致写入文件不完整,BinaryWriter 即可解决。 * 另外在此处,即便是调用了 BinaryWrite 也并未避免 Response.Close() 带来的连接异常问题。 * 虽然 谷歌已经获取到了所有的数据,但并不知道数据的具体长度,仍然会导致解析异常 * 所以还需要加上 Content-Length 参数 */ //Replace { //Response.Write(str); // } to { byte[] b = Response.ContentEncoding.GetBytes(str); Response.BinaryWrite(b); Response.AddHeader("Content-Length", b.Length.ToString()); // } by zhangjing 2016-10-25 Response.Flush(); Response.Close(); } catch { } }