Чтение «кускового» ответа с помощью HttpWebResponse

StackOverflow https://stackoverflow.com/questions/16998

  •  08-06-2019
  •  | 
  •  

Вопрос

У меня возникли проблемы с чтением «кускового» ответа при использовании 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 и проглотить «ошибку».

Это было полезно?

Решение

Не пробовали это с «кусочным» ответом, но будет ли работать что-то подобное?

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);

Другие советы

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

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

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

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

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

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

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

count = resStream.Read(buf, 0, buf.Length-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();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top