WebResponse contentLength属性是-1?

Ric*_*ray 1 c# httpwebrequest httpwebresponse http-content-length web

我有一个Windows应用程序,可以获取URL和下载.jpeg文件.对于某些url,ContentLength属性为-1,因此抛出异常.

这是我的代码:

var url = new Uri(sUrlToReadFileFrom[i]);
_request = (HttpWebRequest)WebRequest.Create(url);
var response = (System.Net.WebResponse)_request.GetResponse();
_response = response;
_response.Close();
Run Code Online (Sandbox Code Playgroud)

这是网址:http: //photos.autonexus.com/imager/115-005-CA/P2GTPI4AB9/640/10132013133959/1FAHP0HA3AR373228_1.jpg 这里有一些关于我的http请求的信息:

Headers = {Transfer-Encoding: chunked
Connection: keep-alive
Content-Disposition: inline; filename="phpThumb_generated_thumbnail.jpeg"
Content-Type: image/jpeg
Date: Wed, 12 Nov 2014 00:31:29 GMT
Server: nginx
X-Powered-By: PleskLin}
Run Code Online (Sandbox Code Playgroud)

我认为分块头导致了问题,但我已经谷歌搜索了2天,没有好的解决方案,或者我找不到一个好的解决方案.

以下是错误的屏幕截图: 在此输入图像描述

正如您在第130行中看到的那样,因为_response.ContentLength已经为-1,因此iSize将为-1并且它会在第149行抛出异常.

Jim*_*hel 5

不要求站点提供Content-Length标头,并且不保证它是正确的.所以你不能依赖它.如果您尝试使用ContentLength属性值来分配数组,或者出于任何目的而不是信息,那么您将遇到麻烦.在一般情况下,它根本不可靠.

这很不幸,但你必须解决它.一种解决方案是创建一个MemoryStream.然后从响应流中读取数据块并将其写入内存流.继续,直到响应流结束.然后获取`MemoryStream'缓冲区.

有点痛,但如果ContentLength不可靠的话,这是你能做的最好的事情.

例如:(请注意,我只是抛弃了它,所以它可能不是100%工作.但它应该给你的想法.)

var response = (HttpWebResponse)request.GetResponse();
byte[] data; // will eventually hold the result
// create a MemoryStream to build the result
using (var mstrm = new MemoryStream())
{
    using (var s = response.GetResponseStream())
    {
        var tempBuffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = s.Read(tempBuffer, 0, tempBuffer.Length)) != 0)
        {
            mstrm.Write(tempBuffer, 0, bytesRead);
        }
    }
    mstrm.Flush();
    data = mstrm.GetBuffer();
}
// at this point, the data[] array holds the data read from the stream.
// data.Length will tell you how large it is.
Run Code Online (Sandbox Code Playgroud)


fej*_*oco 5

很简单:不要使用内容长度标头。如果省略它是完全正常的。只要数据可用,您应该只读取数据。服务器将继续发送它,直到它完成。您可以使用该Stream.CopyTo方法,它将响应流复制到一个文件或一个MemoryStream或任何东西。该方法也不需要知道长度,它只是一直读取直到流结束。

更新:代码是这样的

var resultStream = new MemoryStream()
using (var respStream = response.GetResponseStream())
    respStream.CopyTo(resultStream);
// now you can do anything with resultStream, like resultStream.ToArray()
Run Code Online (Sandbox Code Playgroud)

或者您可以将其写入文件:

using (var fileStream = File.Create(@"d:\x\y.dat"))
using (var respStream = response.GetResponseStream())
    respStream.CopyTo(fileStream);
Run Code Online (Sandbox Code Playgroud)