Чтение "чанкованного" ответа с помощью HttpWebResponse - PullRequest
12 голосов
/ 20 августа 2008

У меня проблемы с чтением отклика "chunked" при использовании StreamReader для чтения потока, возвращаемого GetResponseStream () объекта HttpWebResponse:

// 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, по умолчанию), но это похоже на неудачный обходной путь.

Есть идеи?


@ Чак

Ваше решение работает довольно хорошо. Это все еще бросает то же самое IOExeception в последнем Read (). Но после проверки содержимого StringBuilder похоже, что все данные были получены. Так что, возможно, мне просто нужно обернуть Read () в try-catch и проглотить «ошибку».

Ответы [ 4 ]

3 голосов
/ 20 августа 2008

Не пробовал это с "кусочным" ответом, но что-то вроде этой работы?

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);
1 голос
/ 19 марта 2013

Я работаю над аналогичной проблемой. .Net HttpWebRequest и HttpWebRequest обрабатывают файлы cookie и перенаправляют их автоматически, но они не обрабатывают фрагментированный контент в теле ответа.

Возможно, это связано с тем, что содержимое чанков может содержать не просто данные (т. Е. Имена чанков, конечные заголовки).

Простое чтение потока и игнорирование исключения EOF не сработает, так как поток содержит больше, чем желаемый контент. Поток будет содержать чанки, и каждый чанк начинается с объявления его размера. Если поток просто читается от начала до конца, окончательные данные будут содержать метаданные чанка (и в случае, если это сжатый контент, он не пройдет проверку CRC при распаковке).

Для решения этой проблемы необходимо вручную проанализировать поток, удалив размер фрагмента из каждого фрагмента (а также разделители LF CR), обнаружив окончательный фрагмент и сохранив только данные фрагмента. Вероятно, где-то есть библиотека, которая делает это, я еще не нашел ее.

Полезные ресурсы:

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

0 голосов
/ 09 декабря 2008

У меня была такая же проблема (вот как я здесь оказался :-). В конце концов, это произошло из-за того, что поток чанков был недействительным - отсутствовал последний чанк нулевой длины. Я придумал следующий код, который обрабатывает как действительные, так и недействительные чанкированные потоки.

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();
}
0 голосов
/ 20 августа 2008

Крейг, не видя потока, который вы читаете, его немного сложно отладить, но МОЖЕТЕ изменить настройку переменной count на:

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

Это что-то вроде хака, но если последнее чтение убивает вас и не возвращает никаких данных, то теоретически это поможет избежать проблемы. Мне все еще интересно, почему поток делает это.

...