我有一个获取URL并下载.jpeg
文件的Windows应用程序。对于某些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();
以下是网址: 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}
我认为分块标题导致了问题,但我已经谷歌搜索了2天,没有好的解决方案,或者我找不到好的。
以下是错误的屏幕截图:
正如您在第130行所见,因为_response.ContentLength已经为-1,因此iSize将为-1,并且它会在第149行抛出异常。
答案 0 :(得分: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.
答案 1 :(得分:3)
很简单:不要使用内容长度标题。如果省略它是完全正常的。只要数据可用,您应该只读取数据。服务器将继续发送它直到完成。您可以使用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()
或者您可以将其写入文件:
using (var fileStream = File.Create(@"d:\x\y.dat"))
using (var respStream = response.GetResponseStream())
respStream.CopyTo(fileStream);
答案 2 :(得分:1)
只是为了贡献 - Content-Length标头没有任何问题 - 服务器将其设置为-1,因为它正在返回您的数据'Chunked' - 正如您所推测的那样。分块数据可以是无限的,因此内容长度没有意义。从技术上讲,服务器仍然可以返回一个长度,如果它想知道它将发回的块的聚合大小,虽然我不知道这是否是规范的一部分。
上述解决方案可以解决这个问题 - 但它与Content-Length不可靠无关 - 它与提供它的服务一样可靠。