Question

J'ai du mal à lire une réponse « fragmentée » lorsque j'utilise un StreamReader pour lire le flux renvoyé par GetResponseStream() d'un HttpWebResponse :

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

Quand le reader.ReadToEnd() La méthode est appelée. J'obtiens l'exception System.IO.IOException suivante : Impossible de lire les données de la connexion de transport :La connexion a été fermée.

Le code ci-dessus fonctionne très bien lorsque le serveur renvoie une réponse « non fragmentée ».

La seule façon pour moi de le faire fonctionner est d'utiliser HTTP/1.0 pour la requête initiale (au lieu de HTTP/1.1, la valeur par défaut), mais cela semble être une solution boiteuse.

Des idées?


@Mandrin

Votre solution fonctionne plutôt bien.Il lance toujours la même IOExeception lors de la dernière lecture ().Mais après avoir inspecté le contenu de StringBuilder, il semble que toutes les données aient été reçues.Alors peut-être que j'ai juste besoin d'envelopper le Read() dans un try-catch et d'avaler "l'erreur".

Était-ce utile?

La solution

Je n'ai pas essayé ceci avec une réponse « fragmentée », mais est-ce que quelque chose comme ça fonctionnerait ?

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

Autres conseils

Je travaille sur un problème similaire.Les .net HttpWebRequest et HttpWebRequest gèrent automatiquement les cookies et les redirections, mais ils ne gèrent pas automatiquement le contenu fragmenté sur le corps de la réponse.

Cela est peut-être dû au fait que le contenu fragmenté peut contenir plus que de simples données (c'est-à-dire :noms de fragments, en-têtes de fin).

La simple lecture du flux et l'ignorance de l'exception EOF ne fonctionneront pas car le flux contient plus que le contenu souhaité.Le flux contiendra des morceaux et chaque morceau commence par déclarer sa taille.Si le flux est simplement lu du début à la fin, les données finales contiendront les métadonnées du bloc (et dans le cas où il s'agit de contenu compressé, la vérification CRC échouera lors de la décompression).

Pour résoudre le problème, il est nécessaire d'analyser manuellement le flux, en supprimant la taille du fragment de chaque fragment (ainsi que les délimiteurs CR LF), en détectant le fragment final et en ne conservant que les données du fragment.Il existe probablement une bibliothèque quelque part qui fait cela, je ne l'ai pas encore trouvée.

Ressources utiles :

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

Craig, sans voir le flux que vous lisez, c'est un peu difficile à déboguer mais PEUT-ÊTRE vous pourriez modifier le paramètre de la variable count comme suit :

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

C'est un peu un hack, mais si la dernière lecture vous tue et qu'elle ne renvoie aucune donnée, cela évitera théoriquement le problème.Je me demande toujours pourquoi le flux fait ça.

J'ai eu le même problème (c'est comme ça que je me suis retrouvé ici :-).Finalement, il a été déterminé que le flux fragmenté n'était pas valide - le fragment final de longueur nulle manquait.J'ai trouvé le code suivant qui gère les flux fragmentés valides et invalides.

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top