Voici un extrait du code:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(request.RawUrl);
WebRequest.DefaultWebProxy = null;//Ensure that we will not loop by going again in the proxy
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
string charSet = response.CharacterSet;
Encoding encoding;
if (String.IsNullOrEmpty(charSet))
encoding = Encoding.Default;
else
encoding = Encoding.GetEncoding(charSet);
StreamReader resStream = new StreamReader(response.GetResponseStream(), encoding);
return resStream.ReadToEnd();
Le problème est que si je teste avec: http://www.google.fr
Tous les "é" ne s'affichent pas bien. J'ai essayé de changer ASCII en UTF8 et l'affichage est toujours incorrect. J'ai testé le fichier html dans un navigateur et celui-ci affiche bien le texte html, alors je suis presque sûr que le problème provient de la méthode que j'utilise pour télécharger le fichier html.
Que devrais-je changer?
lien ImageShack mort supprimé
Premièrement, le moyen le plus simple d’écrire ce code est d’utiliser un StreamReader et un ReadToEnd:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(myURL);
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
{
using (Stream resStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(resStream, Encoding.???);
return reader.ReadToEnd();
}
}
Ensuite, il ne reste plus qu’à trouver le bon encodage. Comment avez-vous créé le fichier? Si c'est avec Notepad, vous voudrez probablement Encoding.Default
- mais ce n'est évidemment pas portable, car c'est l'encodage par défaut pour votre PC.
Sur un serveur Web bien géré, la réponse indiquera le codage dans ses en-têtes. Cela dit, les en-têtes de réponse revendiquent parfois une chose et le code HTML en revendique une autre, dans certains cas.
CharacterSet est "ISO-8859-1" par défaut, s'il n'est pas spécifié dans l'en-tête de type de contenu du serveur (différent de la balise méta "charset" en HTML). Je compare HttpWebResponse.CharacterSet avec l'attribut charset de HTML. S'ils sont différents, j'utilise le jeu de caractères spécifié en HTML pour relire à nouveau la page, mais avec un codage correct cette fois-ci.
Voir le code:
string strWebPage = "";
// create request
System.Net.WebRequest objRequest = System.Net.HttpWebRequest.Create(sURL);
// get response
System.Net.HttpWebResponse objResponse;
objResponse = (System.Net.HttpWebResponse)objRequest.GetResponse();
// get correct charset and encoding from the server's header
string Charset = objResponse.CharacterSet;
Encoding encoding = Encoding.GetEncoding(Charset);
// read response
using (StreamReader sr =
new StreamReader(objResponse.GetResponseStream(), encoding))
{
strWebPage = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
// Check real charset meta-tag in HTML
int CharsetStart = strWebPage.IndexOf("charset=");
if (CharsetStart > 0)
{
CharsetStart += 8;
int CharsetEnd = strWebPage.IndexOfAny(new[] { ' ', '\"', ';' }, CharsetStart);
string RealCharset =
strWebPage.Substring(CharsetStart, CharsetEnd - CharsetStart);
// real charset meta-tag in HTML differs from supplied server header???
if(RealCharset!=Charset)
{
// get correct encoding
Encoding CorrectEncoding = Encoding.GetEncoding(RealCharset);
// read the web page again, but with correct encoding this time
// create request
System.Net.WebRequest objRequest2 = System.Net.HttpWebRequest.Create(sURL);
// get response
System.Net.HttpWebResponse objResponse2;
objResponse2 = (System.Net.HttpWebResponse)objRequest2.GetResponse();
// read response
using (StreamReader sr =
new StreamReader(objResponse2.GetResponseStream(), CorrectEncoding))
{
strWebPage = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
}
}
Au cas où vous ne voudriez pas télécharger la page deux fois, j’ai légèrement modifié le code d’Alex à l’aide de Comment puis-je insérer WebResponse dans un flux de mémoire? . Voici le résultat
public static string DownloadString(string address)
{
string strWebPage = "";
// create request
System.Net.WebRequest objRequest = System.Net.HttpWebRequest.Create(address);
// get response
System.Net.HttpWebResponse objResponse;
objResponse = (System.Net.HttpWebResponse)objRequest.GetResponse();
// get correct charset and encoding from the server's header
string Charset = objResponse.CharacterSet;
Encoding encoding = Encoding.GetEncoding(Charset);
// read response into memory stream
MemoryStream memoryStream;
using (Stream responseStream = objResponse.GetResponseStream())
{
memoryStream = new MemoryStream();
byte[] buffer = new byte[1024];
int byteCount;
do
{
byteCount = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, byteCount);
} while (byteCount > 0);
}
// set stream position to beginning
memoryStream.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(memoryStream, encoding);
strWebPage = sr.ReadToEnd();
// Check real charset meta-tag in HTML
int CharsetStart = strWebPage.IndexOf("charset=");
if (CharsetStart > 0)
{
CharsetStart += 8;
int CharsetEnd = strWebPage.IndexOfAny(new[] { ' ', '\"', ';' }, CharsetStart);
string RealCharset =
strWebPage.Substring(CharsetStart, CharsetEnd - CharsetStart);
// real charset meta-tag in HTML differs from supplied server header???
if (RealCharset != Charset)
{
// get correct encoding
Encoding CorrectEncoding = Encoding.GetEncoding(RealCharset);
// reset stream position to beginning
memoryStream.Seek(0, SeekOrigin.Begin);
// reread response stream with the correct encoding
StreamReader sr2 = new StreamReader(memoryStream, CorrectEncoding);
strWebPage = sr2.ReadToEnd();
// Close and clean up the StreamReader
sr2.Close();
}
}
// dispose the first stream reader object
sr.Close();
return strWebPage;
}
Il existe quelques bonnes solutions ici, mais elles semblent toutes essayer d’analyser le jeu de caractères dans la chaîne de type de contenu. Voici une solution utilisant System.Net.Mime.ContentType, qui devrait être plus fiable et plus courte.
var client = new System.Net.WebClient();
var data = client.DownloadData(url);
var encoding = System.Text.Encoding.Default;
var contentType = new System.Net.Mime.ContentType(client.ResponseHeaders[HttpResponseHeader.ContentType]);
if (!String.IsNullOrEmpty(contentType.CharSet))
{
encoding = System.Text.Encoding.GetEncoding(contentType.CharSet);
}
string result = encoding.GetString(data);
C'est le code qui télécharge une fois.
String FinalResult = "";
HttpWebRequest Request = (HttpWebRequest)System.Net.WebRequest.Create( URL );
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
Stream ResponseStream = Response.GetResponseStream();
StreamReader Reader = new StreamReader( ResponseStream );
bool NeedEncodingCheck = true;
while( true )
{
string NewLine = Reader.ReadLine(); // it may not working for zipped HTML.
if( NewLine == null )
{
break;
}
FinalResult += NewLine;
FinalResult += Environment.NewLine;
if( NeedEncodingCheck )
{
int Start = NewLine.IndexOf( "charset=" );
if( Start > 0 )
{
Start += "charset=\"".Length;
int End = NewLine.IndexOfAny( new[] { ' ', '\"', ';' }, Start );
Reader = new StreamReader( ResponseStream, Encoding.GetEncoding(
NewLine.Substring( Start, End - Start ) ) ); // Replace Reader with new encoding.
NeedEncodingCheck = false;
}
}
}
Reader.Close();
Response.Close();
J'ai étudié le même problème à l'aide de WireShark, un excellent analyseur de protocole. Je pense qu'il y a des problèmes de conception dans la classe httpWebResponse. En fait, l'entité de message entière a été téléchargée la première fois que vous avez appelé la méthode GetResponse () de la classe HttpWebRequest, mais le cadre n'a pas de place pour stocker les données dans la classe HttpWebResponse ou ailleurs, vous devez donc obtenir le flux de réponse. la deuxième fois.
Il existe encore quelques problèmes lors de la demande de la page Web "www.google.fr" à un WebRequest.
J'ai vérifié la demande brute et la réponse avec Fiddler. Le problème vient des serveurs de Google. Les en-têtes HTTP de réponse sont définis sur charset = ISO-8859-1, le texte lui-même est codé avec ISO-8859-1, tandis que le code HTML indique charset = UTF-8. Ceci est incohérent et conduit à des erreurs de codage.
Après de nombreux tests, j'ai réussi à trouver une solution de contournement. Il suffit d'ajouter :
myHttpWebRequest.UserAgent = "Mozilla/5.0";
à votre code, et Google Response deviendra comme par magie et entièrement UTF-8.