2008-08-19 9 views
12
私はHttpWebResponseののGetResponseStreamによって返されたストリームを()読み取るためのStreamReaderを使用した場合の応答を「チャンク」を読んトラブルを抱えてい

読書は「チャンク」応答HttpWebResponseの

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

reader.ReadToEnd()方法があります次のSystem.IO.IOExceptionを取得しています。トランスポート接続からデータを読み取れません。接続が閉じられました。

上記のコードは、サーバーが「チャンクなし」応答を返すときにうまく機能します。

私はそれを動作させることができた唯一の方法は、最初の要求(HTTP/1.1ではなく、デフォルト)でHTTP/1.0を使用することですが、これは不自然な回避策のようです。

アイデア?


@Chuck

あなたの解決策は、かなり良い作品。それは最後のRead()に同じIOExeceptionをスローします。しかし、StringBuilderの内容を調べると、すべてのデータが受信されたように見えます。だから、おそらく私はちょうどtry-catchでRead()をラップし、 "エラー"を飲み込む必要があります。

+0

チャンク応答を読み取るには、あなたがhttp://en.wikipedia.org/wiki/Chunked_transfer_encoding –

+0

を実行する必要があり、私は、.NET 4.6でこの振る舞いを見ていますPowerDNS 3.4.5 HTTP REST APIに接続します。回避策は役に立たない。私が例外を飲み込むと、私は応答の一部を失う。 –

答えて

4

「チャンク」レスポンスでこれを試したことはありませんが、この作品のようなものでしょうか?

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

これは、読み込みが文字境界に揃うという保証がないため、マルチバイトエンコーディング(ASCII以外)には危険です。 – spender

+2

@Chuck ASCIIを使用するだけでは、実際にどのエンコーディングが使用されているのか、つまりContent-Typeによって把握し、それを "GetString"に使用する必要があります –

0

クレイグ、あなたが読んでいるストリームを見ることなく、それはデバッグが少し難しいですが、多分あなたはこれにカウント変数の設定を変更することができます:

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

それはハックのビットですしかし、最後の読み取りがあなたを殺していて、それが理論的に問題を回避するなら、それでデータを返さないならば。私はまだストリームがそれをやっているのは不思議です。

0

私は同じ問題を抱えています(これは私がここで終わったところです:-)。最終的には、チャンクされたストリームが有効ではないという事実まで追跡しました。最終的な長さゼロのチャンクはありませんでした。私は、有効なチャンクストリームと無効なチャンクストリームの両方を扱う次のコードを考え出しました。

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

バイトをcharにキャストすることは危険です。マルチバイトエンコーディング – spender

1

私は同様の問題に取り組んでいます。 .net HttpWebRequestとHttpWebRequestは自動的にクッキーとリダイレクトを処理しますが、応答本体のチャンクされたコンテンツは自動的に処理されません。

おそらく、チャンクされたコンテンツに単純なデータ(チャンク名、末尾のヘッダー)以上のデータが含まれる可能性があります。

ストリームに目的のコンテンツ以上が含まれているため、ストリームを読み取り、EOF例外を無視するだけでは機能しません。ストリームにはチャンクが含まれ、各チャンクはそのサイズを宣言することから始まります。ストリームが単純に最初から最後まで読み込まれる場合、最終データにはチャンクメタデータが含まれます(gzipされたコンテンツの場合は、解凍時にCRCチェックに失敗します)。

問題を解決するには、ストリームを手動で解析し、各チャンク(CR LFデリミタと同様)からチャンクサイズを削除し、最終チャンクを検出し、チャンクデータのみを保持する必要があります。そこにはおそらくどこかでこれを行うライブラリがありますが、まだ見つかりませんでした。

お役立ちリソース:

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

関連する問題