2008-08-19 23 views
12
Bir HttpWebResponse GetResponseStream tarafından döndürülen akışı() okumak için bir StreamReader kullanırken bir yanıt "chunked" okuma sorun yaşıyorum

:Okuma "chunked" yanıtı HttpWebResponse

// response is an HttpWebResponse 
StreamReader reader = new StreamReader(response.GetResponseStream()); 
string output = reader.ReadToEnd(); // throws exception... 

reader.ReadToEnd() yöntemdir şu System.IO.IOException alıyorum denir: Aktarım bağlantısından veri okunamıyor: Bağlantı kapatıldı.

Yukarıdaki kod, sunucu "yığınlanmamış" bir yanıt döndürdüğünde düzgün çalışır.

Çalışmayı başarabilmemin tek yolu, ilk istek için HTTP/1.0 kullanmaktır (HTTP/1.1 yerine, varsayılan), ancak bu durum işten çıkarmaya benzer.

Herhangi bir fikrin var mı?


@Chuck

Çözümün oldukça iyi çalışıyor. Hala son Read() 'da aynı IOExeception atar. Ancak StringBuilder'ın içeriğini inceledikten sonra, tüm verilerin alındığı anlaşılıyor. Bu yüzden belki de Read() 'ı bir try-catch'a sarmak ve "hatayı" yutmak zorundayım.

+0

yığın halinde yanıtı okumak için, http://en.wikipedia.org/wiki/Chunked_transfer_encoding ben .NET 4.6 ile bu davranış görüyorum –

+0

izlemeniz gerekir PowerDNS 3.4.5 HTTP REST API'sine bağlanma. Çözümler yardımcı olmuyor. İstisnai yutursam, cevabın bir kısmını kaybederim. –

cevap

4

Bunu "yığınlanmış" bir yanıtla denemediniz, ancak bu gibi bir şey ister misiniz?

StringBuilder sb = new StringBuilder(); 
Byte[] buf = new byte[8192]; 
Stream resStream = response.GetResponseStream(); 
string tmpString = null; 
int count = 0; 
do 
{ 
    count = resStream.Read(buf, 0, buf.Length); 
    if(count != 0) 
    { 
      tmpString = Encoding.ASCII.GetString(buf, 0, count); 
      sb.Append(tmpString); 
    } 
}while (count > 0); 
+4

Bu, çok baytlı kodlamalar için tehlikelidir (yani ASCII değil) çünkü okumaların char sınırlarına hizalanacağının bir garantisi yoktur. – spender

+2

@Chuck ASCII'yi kullanamazsınız, aslında hangi kodlamanın aslında kullanıldığını, yani Content-Type kullanarak ve "GetString" için kullanın –

0

Craig, dere görmeden bunu debug biraz zor okuyorsanız ama BELKİ şuna sayım değişkenin ayarını değiştirebilir: Bir kesmek biraz

count = resStream.Read(buf, 0, buf.Length-1); 

ama eğer son okuma sizi öldürüyorsa ve herhangi bir veriyi geri göndermiyorsa, o zaman teorik olarak bu problemi önleyecektir. Akıntının bunu neden yaptığını hala merak ediyorum.

0

Aynı problemi yaşadım (burada nasıl sonuçlandım :-). Sonunda, parçalanmış akışın geçerli olmadığı gerçeğine kadar izledi - son sıfır uzunluktaki yığın eksikti. Geçerli ve geçersiz yığın akışları ele alan aşağıdaki kodla geldim.

using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) 
{ 
    StringBuilder sb = new StringBuilder(); 

    try 
    { 
     while (!sr.EndOfStream) 
     { 
      sb.Append((char)sr.Read()); 
     } 
    } 
    catch (System.IO.IOException) 
    { } 

    string content = sb.ToString(); 
} 
+2

Karakterize bayt baytının char için tehlikelidir çünkü tamamen yoksayılır çok baytlı kodlamalar. – spender

1

Benzer bir sorun üzerinde çalışıyorum. .net HttpWebRequest ve HttpWebRequest çerezleri otomatik olarak yönlendirir ve yönlendirir, ancak otomatik olarak yanıt gövdesinde parçalanmış içeriği işlemez. Bu, yığınlanmış içeriğin basit verilerden daha fazlasını içerebilmesi nedeniyle olabilir (yani: yığın isimleri, son satır başlıkları).

Akışı okumak ve EOF istisnasını göz ardı etmek, akış istenen içerikten fazlasını içerdiğinden çalışmaz. Akış parçalar içerecek ve her bir parça büyüklüğünü ilan ederek başlıyor. Akım baştan sona okunacak şekilde okunursa, son veriler yığın meta-verisini içerecektir (ve gziped içeriğinin olması durumunda sıkıştırmanın açılması sırasında CRC kontrolünü bozacaktır).

Sorunu çözmek için, akışları el ile ayrıştırmak, her bir öğeden (CR LF sınırlayıcılar kadar) yığın boyutunu kaldırmak, son yığını algılamak ve yalnızca yığın verileri tutmak gerekir. Muhtemelen bulamadığım bir yerde bir kütüphane var.

Faydalı kaynaklar:

http://en.wikipedia.org/wiki/Chunked_transfer_encoding http://tools.ietf.org/html/rfc2616#section-3.6.1