Kaum hat man ein Zeichensatz-Problem in den Griff bekommen, lauert das nächste. Dabei könnte alles so einfach sein. Wenn doch laut landläufiger Meinung UTF-8 die Lösung aller Zeichensatzprobleme ist, warum wird es dann nicht überall als Standard verwendet. Ganz nach dem Motto: Wenn ich nichts angebe meine ich UTF-8. Es könnte alles so einfach sein. Ist es aber nicht. Nicht nur, dass die Lösung aller Probleme nicht dem Standardverhalten der Browser entspricht, es wird auch noch höchst unterschiedlich mit Zeichensatzangaben umgegangen.
Während die Meta-Angabe des Zeichensatzes beim Firefox für eine richtige Interpretation von nicht Ascii Zeichen sorgt, passiert beim InternetExplorer gar nichts. Die Meta-Angabe hat für den IE keine Bedeutung. Entscheidend ist, was im Response-Header des Servers steht. Und so kommt es eben dazu, dass auch bei Ajax-Post-Requests die Übermittlung der Parameter zu einer Fehlerhaften Dekodierung seitens eines Servlets, oder JSPs führt.
Hierfür gibt es einen Verführerischen, aber leider falschen Lösungsansatz: Wenn die Parameter im falschen Format kommen, kodiere ich sie einfach um. Das funktioniert folgendermaßen:
String sParam = request.getParameter("sParam");
if(sParam!=null)
{
sParam= new String(sParam.getBytes(),"UTF-8");
}
Leider führt dies nur im InternetExplorer zu richtigen Ergebnis, denn die anderen Browser machen ja Zeichensatztechnisch alles richtig. Schauen wir uns mal den Grund für das Dilemma näher an:
Um einen Ajax-Post-Request korrekt zu senden ist ungefähr folgende Methode vonnöten:
function doRequest(sFile,session,query)
{
http = getHTTPObject();
try
{
theURL = sFile;
if(theURL.indexOf("?")!=-1)
{
theURL = theURL.substring(0,sFile.indexOf("?"));
}
if(session!=''&& sFile.indexOf("jsessionid")==-1)
{
theURL+=";jsessionid=" + session;
}
else
{
if(theURL.indexOf("?")==-1)
{
theURL += "?";
}
}
http.onreadystatechange = handleHttpResponse;
http.open("POST", theURL, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", query.length);
http.setRequestHeader("Connection", "close");
http.send(query);
}
catch(e)
{
alert(e + ' ' + i + ' ' + theURL );
}
}
So oder Ähnlich findet man es in den meisten Beispielen. Kurz zur Erklärung der Parameter:
Hinsichtlich des Parameters query ist zu beachten, dass dieser Kodiert sein müssen. In den Meisten Tutorials findet man dazu den Hinweis, dass die escape(String) Funktion zu verwenden sei. Das ist leider falsch. Der Grund dafür ist darin zu suchen, das escape(String) in Abhängigkeit vom Browser unterschiedliche Ergebnisse liefert. So war der InternetExplorer in meinen Tests beispielsweise nicht dazu zu bewegen, die übergebenen Parameter UTF-8 zu kodieren. Verwendet wurde, trotz der Angabe des Zeichensatzes in den Meta-Tags der Standardzeichensatz des Betriebssystems (Im Falle von Windows CPC1252). Das bedeutet, dass die Methode zum kodieren von Parametern, wofür sie eigentlich vorgesehen war, völlig ungeeignet ist.
Abhilfe schafft hier die Methode encodeURIComponent(String). Das bedeutet, dass die Parameter für query wie folgt zusammengesetzt werden müssen:
query = ‘parameter1=’ + encodeURIComponent(‘wert1′) + “&” + ‘parameter2=’ + encodeURIComponent(‘wert2′);
Trotzdem wird das oben genannte JavaScript im Internetexplorer zu oben gennanten Problemen führen. Die Lösung ist recht simpel: Der gesetzte Content-Type application/x-www-form-urlencoded ist nicht vollständig. Er führt bei dem Script dazu, dass der IE die Zeichensatzkodierung nicht übermittelt. Wir müssen den Content-Type also noch wie folgt ändern: application/x-www-form-urlencoded;charset=UTF-8
Die in Komination mit der Verwendung der Methode encodeURIComponent(String) löst unser Problem.
[...] Auf die JavaScript Variante gehe hier ein. Damit also keine unerwarteten Zeichensalat-Effekte auftreten sollte jedes Formular wie folgt aussehen: [...]
Hi,
dachte eigentlich, dass ich bei meinen Ajax-Calls (mittlerweile mit jQuery) bei Nutzung von encodeURIComponent und in der Ajax-Datei von utf8_encode/utf8_decode das Problem mit Sonderzeichen behoben hätte. Hatte aber bisher wohl immer mit Umlauten gearbeitet (welche eben kein Problem darstellen), aber nie Sonderzeichen wie typografische Anführungszeichen oder “echte” Gedankenstriche (wie “—” oder “–”) benutzt — selbst wenn ich dem jQuery-Ajax-Aufruf “application/x-www-form-urlencoded;charset=UTF-8″ mit auf den Weg gebe, alle HTML-/PHP-Dateien in UTF-8 kodiert habe, bekomm ichs nicht gebacken.
Kann Deine Lösung auch mit den genannten Sonderzeichen umgehen?
Gruß, Carlos
Die Lösung funktioniert auch mit Deinen Sonderzeichen. Wichtig ist, dass auch das Lesen der Zeichen Fehlschlagen kann. Wenn die von Dir verwendete Engine zum Lesen der Daten beispielsweise das JSON-Format verwendet, ist darauf zu achten, dass Zeichen wie Doppelte Anführungsstriche auch mit einem Backslash maskiert werden.
Hallo Jakob,
entschuldige meine späte Reaktion. Doch ich habe mich nochmals meines Problems angenommen — und muss nun verwundert feststellen, dass ich überhaupt keine Probleme mit irgendwelchen Sonderzeichen habe, wenn ich in der Datei, der ich per Ajax Daten eines Formulars übergebe und die diese Daten wieder (in bearbeiteter Form) zurück gibt, gar nicht erst mit UTF8 arbeite.
“Früher” hatte ich, wenn ich mich recht entsinne, Probleme mit Umlauten gehabt. Erst mit Verwendung von (per PHP) utf8_decode der übergebenen Variablen und mit Rückgabe über utf8_encode hatte ich dies lösen können — bis auf die oben geschilderten Probleme zB mit (langen) Gedankenstrichen, typografischen Anführungszeichen etc.
Nun, wo ich die (De-)Codierung weglasse, überraschenderweise generell kein Zeichensalat mehr. Keine Ahnung, was ich vielleicht an anderer Stelle geändert haben könnte.
Carlos
Hi, dieser Tip hat mir sehr geholfen, DANKE. Beim Request sind mir immer die ‘+’ Zeichen verschwunden, jetzt nicht mehr, tolle arbeit
[...] http://www.buildblog.de/2009/05/01/ajax-und-umlaute-das-ewig-wahrende-utf-8-problem-und-seine-losung... [...]