Comment décoder correctement unicode paramètres passés à une servlet
Supposons que j'ai:
<a href="http://www.yahoo.com/" target="_yahoo"
title="Yahoo!™" onclick="return gateway(this);">Yahoo!</a>
<script type="text/javascript">
function gateway(lnk) {
window.open(SERVLET +
'?external_link=' + encodeURIComponent(lnk.href) +
'&external_target=' + encodeURIComponent(lnk.target) +
'&external_title=' + encodeURIComponent(lnk.title));
return false;
}
</script>
J'ai confirmé external_title
encodés comme Yahoo!%E2%84%A2
et passé à SERVLET
. Si dans SERVLET
je fais:
Writer writer = response.getWriter();
writer.write(request.getParameter("external_title"));
- Je obtenir Yahoo!â"¢ dans le navigateur. Si je le changer manuellement le navigateur de codage de caractères UTF-8, il se transforme en Yahoo!TM (qui est ce que je veux).
Alors j'ai pensé que l'encodage j'ai été l'envoi au navigateur a été mauvais (il a été Content-type: text/html; charset=ISO-8859-1
). J'ai changé SERVLET
à:
response.setContentType("text/html; charset=utf-8");
Writer writer = response.getWriter();
writer.write(request.getParameter("external_title"));
Maintenant le navigateur de codage de caractères UTF-8, mais elle renvoie Yahoo!⢠et je ne peux pas obtenir le navigateur de rendre le caractère correct du tout.
Ma question est: est-il une combinaison de Content-type
et/ou new String(request.getParameter("external_title").getBytes(), "UTF-8");
et/ou quelque chose d'autre qui entraînera Yahoo!TM figurant dans le SERVLET
de sortie?
Vous devez vous connecter pour publier un commentaire.
Vous êtes presque là. EncodeURIComponent correctement encode en UTF-8, qui est ce que vous devriez toujours utiliser une URL aujourd'hui.
Le problème est que le soumis de la chaîne de requête est prise en mutilé sur le chemin de votre script côté serveur, parce que getParameter() utilise la norme ISO-8559-1 au lieu de UTF-8. Cette situation découle de l'Antiquité, avant que le web s'installe sur UTF-8 pour les URI/IRI, mais c'est plutôt pathétique que la Servlet spec n'a pas été mis à jour pour correspondre à la réalité, ou au moins fournir un système fiable, a appuyé l'option pour elle.
(Il y a demande.setCharacterEncoding dans le Servlet 2.3, mais il n'a pas d'incidence sur la chaîne de requête de l'analyse, et si un seul paramètre a été lu avant, éventuellement par un autre élément du cadre, ça ne marchera pas à tous.)
Si vous avez besoin de futz autour de conteneurs-méthodes spécifiques pour obtenir bon UTF-8, impliquant souvent des trucs dans server.xml. Ce totalement suce pour la distribution des applications web qui devraient travailler de n'importe où. Pour Tomcat voir http://wiki.apache.org/tomcat/FAQ/CharacterEncoding et aussi Quelle est la différence entre "URIEncoding" de Tomcat, Filtre de Codage et de la demande.setCharacterEncoding.
request.getParameter("name")
imprime commeÏηγÏÏÏÏη
.request.getQueryString()
imprime commename=%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7
- qui, adoptée àURLDecoder.decode()
est décodé amende. Pourriez-vous s'il vous plaît commentaire sur pourquoi ne pasgetParameter()
retour le pourcentage chaîne codée ? N'est pas ISO-8559-1 un sur-ensemble de l'ASCII ?getParameter
est destiné à prendre soin de décodage de l'entrée pour vous - navigateurs coder les valeurs d'un formulaire avec des % lors de la soumission de sorte que vous avez à les décoder pour obtenir l'entrée de l'utilisateur. Il doit y avoir de l'encodage utilisé pour transformer les octets dans l'entrée, dans les caractères, et les navigateurs ne pas toujours utiliser le même encodage. Malheureusement Servlet choisit pour vous, il ne choisit pas bien, et il ne veut pas vous laisser ignorer ce choix - à la différence deURLDecoder.decode
il n'y a pas deenc
argument.getQueryString()
et d'analyser vous-même au lieu de laisser le Servlet de le faire.J'ai eu le même problème et résolu par le décodage
Request.getQueryString()
à l'aide de URLDecoder(), et après l'extraction de mes paramètres.getParameter
, cependant ce n'est pas tout à fait juste: il doit URL-décoder après fractionnement des composants à part, plutôt qu'avant. Le code ci-dessus serait un échec pour toute utilisation de la&
de caractères en paramètres (codé à%26
), ou=
dans les noms de paramètres (%3D
).Il y a moyen de le faire en java (pas de jongler avec
server.xml
)Ne fonctionnent pas :
Travaux:Travaillé mais céder si l'encodage par défaut != utf-8 - essayez plutôt ceci (omettre l'appel à decode (), il n'est pas nécessaire):
Comme je l'ai dit ci-dessus si la
server.xml
est foiré avec comme dans :(avis de l'
URIEncoding="UTF-8"
) le code ci-dessus va casser (cause de lagetBytes("iso-8859-1")
devrait liregetBytes("UTF-8")
). Donc, pour l'épreuve des balles solution que vous avez pour obtenir la valeur de laURIEncoding
attribut. Cela semble être malheureusement conteneur spécifique pire, de conteneur de version spécifique. Pour tomcat 7 vous auriez besoin de quelque chose comme :Et encore vous avez besoin d'ajuster ce pour plusieurs connecteurs (vérifier le commentaire sur les pièces). Ensuite, vous utilisez quelque chose comme :
Encore cela peut échouer (IIUC) si
parameter = request.getParameter("name");
décodé avec CHARSET_FOR_URI_ENCODING a été corrompu les octets-je obtenir avec getBytes() n'étaient pas ceux d'origine (c'est pourquoi "iso-8859-1" est utilisé par défaut - il permettra de préserver les octets). Vous pouvez se débarrasser de tout cela manuellement par l'analyse de la chaîne de requête dans le sens de:je suis toujours à la recherche de la place dans les docs où il est mentionné que
request.getParameter("name")
fait appelURLDecoder.decode()
au lieu de retourner le%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7
chaîne ? Un lien dans la source serait très apprécié.Aussi, comment puis-je passer comme paramètre la valeur de la corde, pour dire,=> voir le commentaire :%CE
?parameter=%25CE
%CE
il vous suffit de le coder, doncparameter=%25CE
Je soupçonne que les données de la mutilation qui se passe dans la demande, c'est à dire la déclaration de l'encodage de la requête ne correspond pas à celui qui est effectivement utilisé pour les données.
Ce n'
request.getCharacterEncoding()
retour?Je ne sais pas vraiment comment JavaScript poignées de codages ou comment utiliser un spécifique.
Vous devez vous assurer que les encodages sont utilisés correctement à toutes les étapes, ne PAS essayer de "réparer" les données à l'aide de
new String()
ungetBytes()
à un point où il a déjà été codé de manière incorrecte.Edit: Il peut aider à l'origine de la page (celui avec le Javascript) aussi encodé en UTF-8 et déclarée comme telle dans son Type de Contenu. Alors je crois que le Javascript par défaut en UTF-8 pour sa demande -, mais ce n'est pas une connaissance précise, juste une conjecture.
Vous pouvez toujours utiliser javascript pour manipuler le texte.
Je pense que je peux obtenir à la suite de travaux:
Qui me donne
%25u2122
(pour ™) ou%25AE
(pour ®), ce qui permettra de décoder pour%u2122
et%AE
respectivement dans la servlet.Je dois être capable de tourner %u2122 en
'\u2122'
et %AE dans'\u00AE'
relativement facilement à l'aide de(char) (base-10 integer value of %uXXXX or %XX)
dans un match et remplacer la boucle à l'aide d'expressions régulières.savoir - match
/%u([0-9a-f]{4})/i
, extrait de la correspondance de sous-expression, de les convertir en base 10, de le transformer en un char et l'ajouter à la sortie, puis faites de même avec/%([0-9a-f]{2})/i
Il y a un bug dans certaines versions de la Jetée qui le rend analyser plus grand nombre de caractères UTF-8 de manière incorrecte. Si votre serveur accepte les lettres arabes correctement mais pas les emoji, c'est un signe que vous avez une version avec ce problème, car l'arabe n'est pas en ISO-8859-1, mais c'est dans le bas de la fourchette de caractères UTF-8 ("inférieur" sens java va représenter dans un seul char).
J'ai mis à jour à partir de la version 7.2.0.v20101020 à la version 7.5.4.v20111024 et le problème est résolu; je peux maintenant utiliser la getParameter(String) méthode au lieu d'avoir à analyser moi-même.
Si vous êtes vraiment curieux, vous pouvez aller dans votre version de org.eclipse.la jetée.util.Utf8StringBuilder.append(byte) et voir si il ajoute correctement plusieurs caractères de la chaîne lors de l'utf-8 code est assez élevé ou si, comme dans 7.2.0, tout simplement, il jette un int à un char et ajoute.
Merci pour tout ce que j'obtiens à savoir à propos de l'encodage décodage de jeu de caractères par défaut que l'utilisation de tomcat, jetty
J'utilise cette méthode pour résoudre mes problèmes à l'aide de google goyave