12


3

HttpWebResponseで「チャンク」レスポンスを読む

StreamReaderを使用してHttpWebResponseのGetResponseStream()によって返されたストリームを読み取るときに、「チャンクされた」応答を読み取ることができません。

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

`reader.ReadToEnd()`メソッドが呼び出されると、次のSystem.IO.IOExceptionが発生します。トランスポート接続からデータを読み取れません:接続が閉じられました。

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

動作させることができた唯一の方法は最初のリクエストにHTTP / 1.0を使用することです(デフォルトのHTTP / 1.1の代わりに)が、これは時間がかかる回避策のようです。

何か案は?

'' '' '

@チャック

あなたの解決策はかなりうまくいきます。 それはまだ最後のRead()で同じIOExeceptionを投げます。 しかし、StringBuilderの内容を調べたところ、すべてのデータが受信されたように見えます。 そのため、おそらく私はただRead()をtry-catchでラップして「エラー」を飲み込む必要があります。

4 Answer


3


「チャンク」応答でこれを試してみたことはありませんが、このようなことはしますか?

StringBuilder sb = new StringBuilder(); Byte [] buf = new byte [8192];ストリームresStream = response.GetResponseStream();ストリング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);


1


私は同様の問題に取り組んでいます。 .net HttpWebRequestとHttpWebRequestはCookieを処理して自動的にリダイレクトしますが、レスポンスボディのチャンクコンテンツは自動的には処理しません。

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

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

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

有用なリソース:


-1


あなたが読んでいるストリームを見なくてもCraigは、デバッグするのが少し難しいです、しかし、あなたはこれにcount変数の設定を変えることができるかもしれません:

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

ちょっとしたハックですが、最後の読み取りがあなたを殺していてデータを返さないのであれば、理論的にはこれで問題は回避できます。 私はまだストリームがそれをやっている理由は疑問に思う。


-1


私は同じ問題を抱えていました(それが私がここで終わった方法です:-)。 最終的には、チャンクストリームが有効ではなかったという事実まで追跡しました - 最後の長さ0のチャンクがありませんでした。 有効なチャンクストリームと無効なチャンクストリームの両方を処理する次のコードを思い付きました。

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

{while(!sr.EndOfStream){sb.Append((char)sr.Read());を試してください。 catch(System.IO.IOException){}

文字列コンテンツ= sb.ToString(); }