Usuario de Internet, blog personal de Fernando García Torres

Error en la codificación con AJAX

¿Matrix utiliza UTF-8?

Pelearse con la codificación de los caracteres en una aplicación web es pan nuestro de cada día. En un desarrollo sencillo uno puede olvidarse de ese detalle y dejar el trabajo de cloacas al navegador y el PHP. Pero en el momento en que entran en juego javascript y fuentes externas de datos, es entonces cuando la posibilidades de cagarla se multiplican.

Una de las formas más sencillas de prevenir problemas con la codificación es utilizar siempre UTF-8 para el desarrollo completo de la aplicación. Ésto incluye la base de datos, una línea al principio de todo script:

header('Content-type: text/html; charset=utf-8');

También en los HTML:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

Y por supuesto, que el fichero esté físicamente codificado en UTF-8, cosa que cada uno deberá hacer con el editor de código correspondiente (mi experiencia con Ultraedit en este sentido es inmejorable).

El horror comienza cuando no has hecho los deberes, y a una aplicación sencilla se le quiere empezar a meter AJAX y datos de diversas fuentes. Por defecto tu tinglado estará utilizando seguramente ISO 8859-1, la codificación del alfabeto latino, y éso es lo que va a estar esperando el navegador a no ser que le indiques lo contrario…

Mala codificación de los caracteres

Estos problemas de codificación se pueden deber a múltiples razones, sería imposible cubrirlas todas en un post, así que me centraré en las dos con las que he tenido que lidiar estos días:

  • API EXTERNA. Aquí no queda otra, Si la API no ofrece un parámetro para especificar la codificación, va a venir en UTF-8 prácticamente seguro y tocará hacer en el código, por ejemplo en PHP, un utf8_decode de lo que devuelva.
  • AJAX. La diversión con la codificación de caracteres cuando entra en juego el javascript puede no llegar a tener límite. Si, para más inri, utilizamos AJAX para comunicar con un script pongamos de PHP, entonces tenemos todos los ingredientes para la empanada de caracteres raros.

    Obviando detalles de bajo nivel como que el objeto XMLHttpRequest que se encarga de esta comunicación utiliza siempre UTF-8, o que dependiendo de si utilizas GET o POST e Internet Explorer o Firefox se usará una codificación u otra, vemos que las combinaciones pueden marear hasta la náusea, así que hay que buscar una solución que funcione independientemente de la codificación origen-destino, el navegador o el protocolo utilizado.

    Tras varios intentos, dí con una combinación que parece comerse cualquier barbaridad que se pueda poner en un formulario (una caja de texto que acepte código de programación, textos chinos o búlgaros… es un reto). El flujo sería el siguiente:

    1. Desde el javascript mandamos los datos codificados con la función encodeURIComponent (utilizar otra nos dará problemas con los caracteres & y +), por ejemplo:
      ajax.open('get','url_script.php?datos='+encodeURIComponent(datos),true);
    2. Dependiendo del lenguaje de programación que se utilice en el script que recibe los datos habrá que hacer una decodificación o no de los mismos. PHP automáticamente lo realiza para lo que recibe por GET, como en este ejemplo.
    3. Para devolver la respuesta, con PHP utilizamos rawurlencode para codificarla (esta función lo realiza de forma más estricta que urlencode). Por ejemplo:
      echo rawurlencode($respuesta);
    4. Finalmente, de vuelta a javascript, decodificamos la respuesta con decodeURIComponent, y ya tenemos una bonita cadena de caracteres lista para utilizar sin problemas de codificación. Por ejemplo:
      var respuesta = ajax.responseText;
      div.innerHTML = decodeURIComponent(respuesta);

En definitiva, hay que utilizar UTF-8, hay que dejarle al navegador muy claro que lo estamos haciendo, y tenemos que usar una serie de métodos para que en el trasiego de la información entre distintos lenguajes y scripts no se pierda la codificación.

Entradas relacionadas

Scroll infinito con jQuery

5 Comentarios COMENTARIOS RSS RSS de los comentarios de esta entrada

  1. # siciliangirl   10 diciembre, 2008

    Buenos ejemplos de los errores comunes en la codificación que ha más de uno le habrá traído de cabeza en varias ocasiones.
    Aunque se podría aportar algunos ejemplos algo más comunes que algunas API, como por ejemplo:
    mysql_query(“SET NAMES ‘utf8′”) para mysql en PHP, o bien, para la codificación en utf-8 de un XML.
    También recordar de grabar todos los documentos en UTF-8 sin BOOM, a parte de los tags que indican el tipo de codificación del documento.

  2. # Gonza   30 enero, 2010

    Para envío vía AJAX con método POST, me fue útil la función “escape” (aunque el símbolo “+” por algún motivo no lo puede codificar y hay que usar el método “replace” para codificarlo). Espero que a alguien le sirva de ayuda.

  3. # CodeChargeMVP   29 noviembre, 2010

    Buenos Días Fernando,

    He intentado poner en práctica la solución que propones sin mucho éxito, cuando intento decodificar la respuesta que viene desde el script de php, me da un error en esa línea:
    “El identificador URI para descodificar no tiene una codificación valida”.

    la página que hace el request al script de php esta códificada,como bien supones, en ISO 8859-1, el script de php esta códificado en UTF-8 grabado con TotalEdit,¿es posible codificar el script de UTF-8 en ISO 8859-1?

    Quizás sea ese el error.

    He intentado añadir el header que comentas al script de php pero no funciona correctamente así que he tenido que quitarlo.

    Muchas gracias por adelantado.

    Un Saludo muy antentamente Jesús.

  4. # CodeChargeMVP   29 noviembre, 2010

    Afortunadamente he solucionado el problema,
    aparentemente no importa que el script de php este grabado con total edit en una codificación UTF8 o UTF-8.
    Muy a mí pesar tengo que decir que la combinación que sugieres es errónea, no voy a ser tan tajante como en esta página:
    http://www.captain.at/howto-php-urlencode-javascript-decodeURIComponent.php
    Donde aseguran que “todas” las codificaciones de php son incompatibles con las decodificaciones de javascript, esto no es cierto,pero si es cierto que la combinación de rawurlencode de php y decodeURIComponent son incompatibles,genera el error que comentaba antes la combinación correcta es rawurlencode desde php y unescape en javascript.

    Un Saludo Muy Atentamente Jesús.

    • # fer   29 noviembre, 2010

      Hola!
      Tal vez no queda claro en el post, pero estas funciones js de URI SIEMPRE trabajan con UTF-8, por lo tanto el error que recibes es porque desde el PHP no estás enviando datos codificados correctamente, sino en la ISO.
      Cambiarlo por unescape te funciona por esta misma razón, con la ISO-8859-1 es una solución válida, pero siempre es aconsejable trabajar con UTF-8 para olvidarse de problemas de codificación.
      Saludos!

Publicar Comentario

todos los campos son opcionales