HTTP响应内容长度问题解析

在处理HTTP网络请求时,有时会遇到一些棘手的问题,比如Content-Length的值为-1。这种情况通常发生在使用分块传输编码(chunked transfer encoding)时,数据长度超过了某个阈值。尽管网络上的搜索结果并没有给出一个明确的解决方案,但通过使用Fiddler2工具进行测试,推测出了可能的原因,尽管不能确定这就是最终答案。

HTTP响应示例

以下是两个HTTP响应的示例,其中一个的Content-Length是正确的,而另一个则出现了问题。

正确的Content-Length响应:

HTTP/1.1 200 OK Date: Tue, 01 Jan 2013 21:48:42 GMT Server: Apache Content-Disposition: attachment; filename="example.file" Content-Length: 1537 Content-Type: application/octet-stream Content-Language: fr-FR Via: 1.1 some.proxy.server X-Cache: MISS from some.proxy.server Keep-Alive: timeout=15, max=90 Connection: Keep-Alive

Content-Length值错误的响应:

HTTP/1.1 200 OK Date: Tue, 01 Jan 2013 21:48:44 GMT Server: Apache Content-Disposition: attachment; filename="example.file" Content-Type: application/octet-stream Content-Language: fr-FR Via: 1.1 some.proxy.server X-Cache: MISS from some.proxy.server Keep-Alive: timeout=15, max=86 Connection: Keep-Alive Content-Length: 13356

不清楚也不关心为什么HTTP服务器不总是按相同的顺序返回响应头(是否由分块数据引起?),但怀疑.NET Framework(4.0版本)在Content-Length头出现在Connection头之后时会忽略它(如上所示的HTTP响应)。

解决方案

为了解决这个问题,决定忽略Content-Length头,让MemoryStream动态增长,这似乎解决了问题。

这种方法虽然有效,但是否有更好的解决方案或建议呢?

.NET Framework中,MemoryStream类提供了一种动态管理内存的方式,允许在不知道数据大小的情况下读取数据。这种方法避免了在读取HTTP响应时遇到Content-Length为-1的问题。

using System.IO; using System.Net; public byte[] DownloadData(string url) { byte[] buffer = new byte[1024]; using (MemoryStream ms = new MemoryStream()) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream responseStream = response.GetResponseStream()) { int bytesRead; while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) != 0) { ms.Write(buffer, 0, bytesRead); } } } return ms.ToArray(); } }

在上述代码中,创建了一个MemoryStream对象,并使用一个循环读取响应流中的数据。每次读取到数据后,将其写入MemoryStream中。最后,调用ToArray方法将MemoryStream中的数据转换为一个字节数组。

分块传输编码是一种HTTP传输编码,它允许服务器在不知道整个响应内容大小的情况下发送数据。在处理分块传输编码时,服务器会在每个数据块的开始处指定该块的大小,而不是在响应头中指定Content-Length。

为了正确处理分块传输编码,需要逐块读取数据,而不是依赖Content-Length头。以下是一个处理分块传输编码的示例代码:

using System.IO; using System.Net; public byte[] DownloadChunkedData(string url) { byte[] buffer = new byte[1024]; using (MemoryStream ms = new MemoryStream()) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.TransferEncoding = "chunked"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream responseStream = response.GetResponseStream()) { int bytesRead; while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) != 0) { ms.Write(buffer, 0, bytesRead); } } } return ms.ToArray(); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485