11

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.1 ではなく) HTTP/1.0 を使用することですが、これは不十分な回避策のようです。

何か案は?


@チャック

あなたのソリューションはかなりうまくいきます。最後の Read() で同じ IOExeception をスローします。しかし、StringBuilder の内容を調べると、すべてのデータが受信されたように見えます。したがって、おそらく Read() を try-catch でラップして、「エラー」を飲み込む必要があります。

4

5 に答える 5

3

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

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);
于 2008-08-19T23:54:37.670 に答える
1

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

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

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

この問題を解決するには、ストリームを手動で解析し、各チャンク (および CR LF 区切り記号) からチャンク サイズを削除し、最終チャンクを検出して、チャンク データのみを保持する必要があります。これを行うライブラリがどこかにある可能性がありますが、まだ見つけていません。

便利なリソース :

http://en.wikipedia.org/wiki/Chunked_transfer_encoding https://www.rfc-editor.org/rfc/rfc2616#section-3.6.1

于 2013-03-19T10:50:16.453 に答える
-1

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

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();
}
于 2008-12-09T11:26:48.413 に答える