AJAX и проблемы с кодировкой. Проблемы с кодировкой в jQuery Ajax и PHP Ajax кодировка

Я выполняю запрос AJAX к скрипту PHP в JavaScript и с помощью библиотеки jQuery.
Вот моя команда, которая выполняет запрос AJAX:

$. ({ async: "false", cache: "false", data: {login: strLogin, password: strPassword}, datatype: "text", error: connexionAjaxError, success: connexionAjaxSuccess, type: "POST", url: "./Connexion" });

«.Connexion» – это перенаправление URL-адресов на мой PHP-скрипт.
connexionAjaxError – это функция JavaScript, которая неизбежно выполняется, как только получен ответ HTTP.
Причина. Мой PHP-скрипт приводит к текстовой / простой странице с кодом состояния HTTP, равным 500.
Вот наиболее важная часть моего PHP-скрипта:

header("HTTP/1.0 500 Internal Server Error; Content-type: text/plain; charset=ISO-8859-1"); echo "été";

Вот подпись функции callexionAjaxError callback:

Function connexionAjaxError(jqXHR, textStatus, errorThrown)

Мой PHP-результат соответствует строке «été».
Внутренняя кодировка PHP – это ISO-8859-1, поэтому строка результата кодируется в шестнадцатеричной системе.

Но jqXHR.responseText в функции callexionAjaxError вызывает 1-символьную строку.
Я использовал метод charCodeAt объекта JavaScript String для получения кода юникода (UTF-8?) Для символа.
Символ кодируется 65535 в десятичной нотации, эквивалентной в шестнадцатеричной нотации.

Я не понимаю, почему jqXHR.responseText не содержит 3-символьную строку «été».
Я не эксперт в JavaScript, но я полагаю, что jqXHR.responseText может содержать только строку, закодированную в UTF-8.
Таким образом, строка «été» в jqXHR.responseText будет закодирована в шестнадцатеричной нотации.
Я получил код UTF-8 для символа «é» со следующего веб-сайта: http://www.utf8-chartable.de/

Я делаю много развития на испанском языке, и я заметил несколько вещей, которые могут вам помочь, поскольку я уже прошел через это:

Кодировка в функции заголовка должна быть UTF-8.

Кроме того, сам FILE (скрипт PHP) должен быть сохранен в UTF-8, вы можете легко достичь этого, если вы отредактируете файл с помощью Notepad ++ и выберите кодировку UTF-8 без спецификации.

То же самое касается ваших javascript и HTML-файлов, все они должны быть закодированы с помощью UTF-8 без спецификации, а не ANSI.

Дай мне знать!

Попробуйте установить Contenttype, как это в вашем вызове, насколько я знаю jQuery Ajax всегда utf-8, если не указано.

$.ajax({ ... datatype: "text", contentType: "application/x-www-form-urlencoded;charset=ISO-8859-1", error: connexionAjaxError, success: connexionAjaxSuccess, type: "POST", ... });

Изменить: если мой ответ не поможет, это может помочь, если вы проверите конфигурацию набора символов сервера, а также разместите его.

AJAX, - это технология. Одной из часто используемых техник этой технологии является посылка запросов при помощи объекта класса XMLHttpRequest.

Классов то, конечно, в JavaScript нет, но для удобства будем пользоваться такой терминологией.

В документации на XMLHttpRequest сказано, что браузер должен поддерживать следующие типы HTTP- запросов:

GET, POST, HEAD, PUT , DELETE, OPTIONS

На сегодняшний день джаваскриптом через объект класса XMLHttpRequest можно отправить только запросы типа GET и POST .

Итак, рассмотрим 2 этих запроса:

Вся информация скрипту на сервере может передаваться только через URL и через заголовки.

Host: moy-rebenok

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.11) Gecko/20071127

Firefox/2.0.0.11

Accept:

Text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/pn

G,*/*;q=0.5

Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3

Accept-Encoding: gzip,deflate

Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7

Keep-Alive: 300

Connection: keep-alive

Referer: http://moy-rebenok/ajax.html

На сервере, в ajax.php можно будет использовать конструкцию

$_GET["f"], чтобы получить значение переменной f.

Почему встает проблема с русскими буквами? Потому что, как вы знаете, русские буквы в URL использовать нельзя, их необходимо как-то передать при помощи доступных латинских букв, цифр и знаков, допустимых в URL после знака "?".

Люди договорились, что будут делать это при помощи escape-последовательностей.

escape последовательность слова "привет" в кодировке windows-1251:

%EF%F0%E8%E2%E5%F2

escape последовательность слова "привет" в кодировке UTF-8:

%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82

escape последовательность слова "привет" в кодировке KOI8-R:

%CE%CF%D5%C1%C5%D0

(Знак "%", потом код символа).

Таким образом передать русские буквы можно, например, так:

GET http://moy-rebenok/ajax.php?f=%EF%F0%E8%E2%E5%F2

GET http://moy-rebenok/ajax.php?f=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82

Никто вас в этом не ограничивает .

Кстати, для GET запроса не нужно указывать заголовок Content-Type.
Т.к. никакого контента нет. Есть только запрос по определенному адресу.
Все переменные на сервер передаются через URL.
Как же смастерить необходимую escape последовательность в нужной кодировке?
Мастерить можно хоть руками, хоть как, но естественно в JavaScript.
Опять же, никто вас не ограничивает.

Но для удобства обычно используют одну из 3 функций, которые уже определены в JavaScript :

а) escape()

б) encodeURI()

в) encodeURIComponent()

По порядку:

Латинские буквы, цифры, символы @*/+. оставляет как есть, всё остальное кодирует так:

%xx, либо так: %uxxxx.

Причем, xxxx во втором случае, - это код символа не в UTF-8, а в Unicode

Использовать эту функцию не надо , т.к. результат выполнения зависит от браузера, функция не является стандартизированной W3C, возникла в лихие 90-е.

К тому же, как-то нормально (по крайней мере, быстро) обработать строку в таком винигретчатом формате на сервере сложно.

Функцию escape() использует библиотека нашего соотечественника JsHttpRequest.
Не потому что библиотека плохая, а потому что создана для работы со всеми браузерами
(в том числе и с самыми древними).

Латинские буквы, цифры, символы!@#$&*()=:/;?+". оставляет как есть, всё остальное

кодирует

Одобрено W3C.

в) encodeURIComponent():

Латинские буквы, цифры, символы!*()". оставляет как есть, всё остальное кодирует

escape-последовательностями в кодировке UTF-8.

Одобрено W3C.

Используется jQuery, prototype.js при запросе методом GET.

Возможно вы слышали от кого-то: "XMLHttpRequest работает только с UTF-8".
Теперь знаете, что это не совсем правда.

Когда используется GET-запрос, то кодировка переданных данных вообще нигде не прописывается(!).

Ещё раз повторю, "Content-type", в котором мы можем указать charset не используется в GET запросах.

Но, т.к. в JavaScript есть 2 удобные функции для перевода любой строки в строку с escape-последовательностями в UTF-8, то все их используют, и работают с UTF-8.

Именно поэтому в jQuery даже нельзя никак указать charset при отправке запроса.

Именно поэтому в Prototype.js, даже когда указываешь encoding="windows-1251", и используешь GET запрос, то передается всё равно UTF-8.

Просто потому что в кодах этих библиотек используется функция encodeURIComponent().

Что ж. В этом нет совершенно ничего плохого. Всё, что надо сделать, чтобы теперь работать в PHP в нормальной кодировке использовать iconv:

$f = iconv("UTF-8", "windows-1251", $_GET["f"]);

Кстати, мы можем это сделать именно потому, что $_GET работает так, что он понимает

escape-последовательности. Спасибо создателям PHP.

Т.е. когда приходит GET запрос PHP смотрит на URL, создает для нас массив $_GET, а мы
уже с ним что хотим, то и делаем. Но это вроде понятно должно быть.

2) POST-запросы.

Здесь уже всё интереснее.

Вот приходит это запрос на сервер. Обработчик PHP смотрит на Content-type, и в зависимости от него заполняет массив $_POST и/или переменную $HTTP_RAW_POST_DATA.

$_POST он заполняет в том случае, когда в Content-type указано multipart/form-data или

x-www-form-urlencoded.

Что-же это за Content-type такой?

А контент-тайп это очень удобный. Он позволяет передать php скрипту несколько переменных.

Что по сути такое POST запрос?

Это заголовки, а за ними контент. Контент вообще произвольный. Т.е. просто байты, байты, байты.

Но ведь из JavaScript обычно требуется передать не просто байты, байты, байты, а несколько пар ключ=значение, ключ=значение, ...

Как в GET запросе.

Вот люди и договорились о таком удобном типе, как x-www-form-urlencoded

Для того, чтобы передать f=123 и gt=null необходимо передать контент:

Знакомо неправда ли? Конечно знакомо, и тип не зря называется x-www-form-urlencoded.

Всё то же самое, что и при GET запросе.

И как же формируется контент в библиотеках jQuery и prototype.js?

Верно, при помощи всё той же функции encodeURIComponent(), а значит и escape-последовательности будут в кодировке UTF-8. (Независимо от того, что в prototype.js вы установите encoding).

Всё. Осталась ещё одна возможность. Ведь можно передавать не x-www-form-urlencoded (т.е. не параметры), а обычный текстовый или бинарный контент, который потом можно будет прочитать через $HTTP_RAW_POST_DATA.

Для этого устанавливаем Content -type text /xml или application /octet -stream , там же устанавливаем charset="windows-1251".

Засовываем в функцию send() строку нужной кодировки. (Prototype.js оборачивает этот вызов конструкцией new Ajax.Request(...)).

И что потом... А он (объект класса XMLHttpRequest) переводит эту строку в UTF-8, в какой бы кодировке она не была. Так написано в документации W3C. И он реально это делает.

Выводы:

2. Можно передавать строки как бы "в любых других кодировках", если нелатинские символы при этом за-escape-ены.

3. В JavaScript существует 3 функции, которые escape-ят нелатинские символы:

escape(), encodeURI() и encodeURIComponent().

Первая переводит в кривой Unicode. Вторые две в UTF-8.

Можно написать свои функции, которые будут генерировать escape-последовательности любой кодировки. Можно, но не нужно. Т.к. наоборот надо радоваться, что есть такие вот функции, которые переводят текст любой кодировки в UTF-8. Это черезвычайно прекрасный факт. Схема при которой все xhtml страницы работают на windows-1251, ajax с сервера клиенту кидает windows-1251, а ajax с клиента серверу кидает UTF-8 абсолютна приемлема и используется на большинстве ресурсов .

Просто не надо забывать использовать iconv как было описано ниже. А для того, чтобы сервер отдавал яваскрипту JSON (или что там у вас) в правильной кодировке (т.е. в такой же кодировке, в которой отдаются все xhtml страницы) просто в начале вашего ajax.php пропишите заголовок:

header("Content-type: text/html; charset=windows-1251");

И всё будет ок.

На последок немного субъективного мнения:

Используйте jQuery, любите людей, дарите подарки.

17 декабря 2007 в 19:59 Разберемся раз и навсегда: AJAX, «кириллические символы», кодировки, prototype.js, jQuery, JsHttpRequest
  • Разработка веб-сайтов

AJAX, - это технология. Одной из часто используемых техник этой технологии является
посылка запросов при помощи объекта класса XMLHttpRequest.

Как же посылать и принимать AJAX запросы в нужной нам кодировке, нужно ли использовать однобайтовые кодировки или не обойтись без UTF-8. На все эти вопросы раз и навсегда ответит эта статья.

И ещё, классов-то, конечно, в JavaScript нет, но для удобства будем пользоваться такой терминологией.

В документации на XMLHttpRequest сказано, что браузер должен поддерживать следующие типы
HTTP-запросов: GET, POST, HEAD, PUT, DELETE, OPTIONS.

На сегодняшний день джаваскриптом через объект класса XMLHttpRequest можно отправить
только запросы типа GET и POST .

Итак, рассмотрим 2 этих запроса:

Вся информация скрипту на сервере может передаваться только через URL и через заголовки.

На сервере, в ajax.php можно будет использовать конструкцию
$_GET["f"], чтобы получить значение переменной f.

Почему встает проблема с русскими буквами? Потому что, как вы знаете, русские буквы в URL использовать нельзя, их необходимо как-то передать при помощи доступных латинских букв, цифр и знаков, допустимых в URL после знака "?".

Люди договорились, что будут делать это при помощи escape-последовательностей.

Escape последовательность слова «привет» в кодировке windows-1251:
%EF%F0%E8%E2%E5%F2

Escape последовательность слова «привет» в кодировке UTF-8:
%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82

Escape последовательность слова «привет» в кодировке KOI8-R:
%CE%CF%D5%C1%C5%D0

(Знак "%", потом код символа).

Таким образом передать русские буквы можно, например, так:

Никто вас в этом не ограничивает .

Кстати, для GET запроса не нужно указывать заголовок Content-Type.
Т.к. никакого контента нет. Есть только запрос по определенному адресу.
Все переменные на сервер передаются через URL.

Как же смастерить необходимую escape последовательность в нужной кодировке?

Мастерить можно хоть руками, хоть как, но естественно в JavaScript.
Опять же, никто вас не ограничивает.

Но для удобства обычно используют одну из 3 функций, которые уже определены в JavaScript:

А) escape()
б) encodeURI()
в) encodeURIComponent()

По порядку:

Латинские буквы, цифры, символы @*/+. оставляет как есть, всё остальное кодирует так:
%xx, либо так: %uxxxx.
Причем, xxxx во втором случае, - это код символа не в UTF-8, а в Unicode

Использовать эту функцию не надо , т.к. результат выполнения зависит от браузера, функция не является стандартизированной W3C, возникла в лихие 90-е.

К тому же, как-то нормально (по крайней мере, быстро) обработать строку в таком винигретчатом формате на сервере сложно.

Функцию escape() использует библиотека нашего соотечественника JsHttpRequest.
Не потому что библиотека плохая, а потому что создана для работы со всеми браузерами
(в том числе и с самыми древними).

Б) encodeURI()

Латинские буквы, цифры, символы!@#$&*()=:/;?+". оставляет как есть, всё остальное
кодирует

В) encodeURIComponent():

Латинские буквы, цифры, символы!*()". оставляет как есть, всё остальное кодирует
escape-последовательностями в кодировке UTF-8.
Одобрено W3C.

Используется jQuery, prototype.js при запросе методом GET.

Возможно вы слышали от кого-то: «XMLHttpRequest работает только с UTF-8».
Теперь знаете, что это не совсем правда.

Когда используется GET-запрос, то кодировка переданных данных вообще нигде не прописывается(!).
Ещё раз повторю, "Content-type", в котором мы можем указать charset
не используется в GET запросах.

Но, т.к. в JavaScript есть 2 удобные функции для перевода любой строки в строку с escape-последовательностями в UTF-8, то все их используют, и работают с UTF-8.

Именно поэтому в jQuery даже нельзя никак указать charset при отправке запроса.
Именно поэтому в Prototype.js, даже когда указываешь encoding="windows-1251", и используешь GET запрос, то передается всё равно UTF-8.

Просто потому что в кодах этих библиотек используется функция encodeURIComponent().

Что ж. В этом нет совершенно ничего плохого. Всё, что надо сделать, чтобы теперь работать
в PHP в
нормальной кодировке использовать iconv:

$f = iconv("UTF-8", "windows-1251", $_GET["f"]);

Кстати, мы можем это сделать именно потому, что $_GET работает так, что он понимает
escape-последовательности. Спасибо создателям PHP.

Т.е. когда приходит GET запрос PHP смотрит на URL, создает для нас массив $_GET, а мы
уже с ним
что хотим, то и делаем. Но это вроде понятно должно быть.

2) POST-запросы.

Здесь уже всё интереснее.

Вот приходит это запрос на сервер. Обработчик PHP смотрит на Content-type, и в зависимости от него заполняет массив $_POST и/или переменную $HTTP_RAW_POST_DATA.

$_POST он заполняет в том случае, когда в Content-type указано multipart/form-data или
x-www-form-urlencoded.

Что-же это за Content-type такой?
А контент-тайп это очень удобный. Он позволяет передать php скрипту несколько переменных.

Что по сути такое POST запрос?
Это заголовки, а за ними контент. Контент вообще произвольный. Т.е. просто байты, байты, байты.

Но ведь из JavaScript обычно требуется передать не просто байты, байты, байты, а несколько пар ключ=значение, ключ=значение,…
Как в GET запросе.

Вот люди и договорились о таком удобном типе, как x-www-form-urlencoded
Для того, чтобы передать f=123 и gt=null необходимо передать контент:

Знакомо неправда ли? Конечно знакомо, и тип не зря называется x-www-form-urlencoded.
Всё то же самое, что и при GET запросе.

И как же формируется контент в библиотеках jQuery и prototype.js?

Верно, при помощи всё той же функции encodeURIComponent(), а значит и escape-последовательности будут в кодировке UTF-8. (Независимо от того, что в prototype.js вы установите encoding).

Всё. Осталась ещё одна возможность. Ведь можно передавать не x-www-form-urlencoded (т.е. не параметры), а обычный текстовый или бинарный контент, который потом можно будет прочитать через $HTTP_RAW_POST_DATA.

Для этого устанавливаем Content-type text/xml или application/octet-stream, там же устанавливаем charset=«windows-1251».

Засовываем в функцию send() строку нужной кодировки. (Prototype.js оборачивает этот вызов конструкцией new Ajax.Request(...)).

И что потом… А он (объект класса XMLHttpRequest) переводит эту строку в UTF-8, в какой бы кодировке она не была. Так написано в документации W3C. И он реально это делает.

Выводы:

2. Можно передавать строки как бы «в любых других кодировках», если нелатинские символы
при этом за-escape-ены.

3. В JavaScript существует 3 функции, которые escape-ят нелатинские символы:
escape(), encodeURI() и encodeURIComponent().

Первая переводит в кривой Unicode. Вторые две в UTF-8.

Можно написать свои функции, которые будут генерировать escape-последовательности любой кодировки. Можно, но не нужно. Т.к. наоборот надо радоваться, что есть такие вот функции, которые переводят текст любой кодировки в UTF-8. Это черезвычайно прекрасный факт. Схема при которой все xhtml страницы работают на windows-1251, ajax с сервера клиенту кидает windows-1251, а ajax с клиента серверу кидает UTF-8 абсолютна приемлема и используется на большинстве ресурсов .

Просто не надо забывать использовать iconv как было описано ниже. А для того, чтобы сервер отдавал яваскрипту JSON (или что там у вас) в правильной кодировке (т.е. в такой же кодировке, в которой отдаются все xhtml страницы) просто в начале вашего ajax.php пропишите заголовок:

Header("Content-type: text/html; charset=windows-1251");

И всё будет ок.

На последок немного субъективного мнения:

Используйте jQuery, любите людей, дарите подарки.

AJAX, - это технология. Одной из часто используемых техник этой технологии является
посылка запросов при помощи объекта класса XMLHttpRequest.

Как же посылать и принимать AJAX запросы в нужной нам кодировке, нужно ли использовать однобайтовые кодировки или не обойтись без UTF-8. На все эти вопросы раз и навсегда ответит эта статья.

И ещё, классов-то, конечно, в JavaScript нет, но для удобства будем пользоваться такой терминологией.

В документации на XMLHttpRequest сказано, что браузер должен поддерживать следующие типы
HTTP-запросов: GET, POST, HEAD, PUT, DELETE, OPTIONS.

На сегодняшний день джаваскриптом через объект класса XMLHttpRequest можно отправить
только запросы типа GET и POST .

Итак, рассмотрим 2 этих запроса:

Вся информация скрипту на сервере может передаваться только через URL и через заголовки.

На сервере, в ajax.php можно будет использовать конструкцию
$_GET["f"], чтобы получить значение переменной f.

Почему встает проблема с русскими буквами? Потому что, как вы знаете, русские буквы в URL использовать нельзя, их необходимо как-то передать при помощи доступных латинских букв, цифр и знаков, допустимых в URL после знака "?".

Люди договорились, что будут делать это при помощи escape-последовательностей.

Escape последовательность слова «привет» в кодировке windows-1251:
%EF%F0%E8%E2%E5%F2

Escape последовательность слова «привет» в кодировке UTF-8:
%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82

Escape последовательность слова «привет» в кодировке KOI8-R:
%CE%CF%D5%C1%C5%D0

(Знак "%", потом код символа).

Таким образом передать русские буквы можно, например, так:

Никто вас в этом не ограничивает .

Кстати, для GET запроса не нужно указывать заголовок Content-Type.
Т.к. никакого контента нет. Есть только запрос по определенному адресу.
Все переменные на сервер передаются через URL.

Как же смастерить необходимую escape последовательность в нужной кодировке?

Мастерить можно хоть руками, хоть как, но естественно в JavaScript.
Опять же, никто вас не ограничивает.

Но для удобства обычно используют одну из 3 функций, которые уже определены в JavaScript:

А) escape()
б) encodeURI()
в) encodeURIComponent()

По порядку:

Латинские буквы, цифры, символы @*/+. оставляет как есть, всё остальное кодирует так:
%xx, либо так: %uxxxx.
Причем, xxxx во втором случае, - это код символа не в UTF-8, а в Unicode

Использовать эту функцию не надо , т.к. результат выполнения зависит от браузера, функция не является стандартизированной W3C, возникла в лихие 90-е.

К тому же, как-то нормально (по крайней мере, быстро) обработать строку в таком винигретчатом формате на сервере сложно.

Функцию escape() использует библиотека нашего соотечественника JsHttpRequest.
Не потому что библиотека плохая, а потому что создана для работы со всеми браузерами
(в том числе и с самыми древними).

Б) encodeURI()

Латинские буквы, цифры, символы!@#$&*()=:/;?+". оставляет как есть, всё остальное
кодирует

В) encodeURIComponent():

Латинские буквы, цифры, символы!*()". оставляет как есть, всё остальное кодирует
escape-последовательностями в кодировке UTF-8.
Одобрено W3C.

Используется jQuery, prototype.js при запросе методом GET.

Возможно вы слышали от кого-то: «XMLHttpRequest работает только с UTF-8».
Теперь знаете, что это не совсем правда.

Когда используется GET-запрос, то кодировка переданных данных вообще нигде не прописывается(!).
Ещё раз повторю, "Content-type", в котором мы можем указать charset
не используется в GET запросах.

Но, т.к. в JavaScript есть 2 удобные функции для перевода любой строки в строку с escape-последовательностями в UTF-8, то все их используют, и работают с UTF-8.

Именно поэтому в jQuery даже нельзя никак указать charset при отправке запроса.
Именно поэтому в Prototype.js, даже когда указываешь encoding="windows-1251", и используешь GET запрос, то передается всё равно UTF-8.

Просто потому что в кодах этих библиотек используется функция encodeURIComponent().

Что ж. В этом нет совершенно ничего плохого. Всё, что надо сделать, чтобы теперь работать
в PHP в
нормальной кодировке использовать iconv:

$f = iconv("UTF-8", "windows-1251", $_GET["f"]);

Кстати, мы можем это сделать именно потому, что $_GET работает так, что он понимает
escape-последовательности. Спасибо создателям PHP.

Т.е. когда приходит GET запрос PHP смотрит на URL, создает для нас массив $_GET, а мы
уже с ним
что хотим, то и делаем. Но это вроде понятно должно быть.

2) POST-запросы.

Здесь уже всё интереснее.

Вот приходит это запрос на сервер. Обработчик PHP смотрит на Content-type, и в зависимости от него заполняет массив $_POST и/или переменную $HTTP_RAW_POST_DATA.

$_POST он заполняет в том случае, когда в Content-type указано multipart/form-data или
x-www-form-urlencoded.

Что-же это за Content-type такой?
А контент-тайп это очень удобный. Он позволяет передать php скрипту несколько переменных.

Что по сути такое POST запрос?
Это заголовки, а за ними контент. Контент вообще произвольный. Т.е. просто байты, байты, байты.

Но ведь из JavaScript обычно требуется передать не просто байты, байты, байты, а несколько пар ключ=значение, ключ=значение,…
Как в GET запросе.

Вот люди и договорились о таком удобном типе, как x-www-form-urlencoded
Для того, чтобы передать f=123 и gt=null необходимо передать контент:

Знакомо неправда ли? Конечно знакомо, и тип не зря называется x-www-form-urlencoded.
Всё то же самое, что и при GET запросе.

И как же формируется контент в библиотеках jQuery и prototype.js?

Верно, при помощи всё той же функции encodeURIComponent(), а значит и escape-последовательности будут в кодировке UTF-8. (Независимо от того, что в prototype.js вы установите encoding).

Всё. Осталась ещё одна возможность. Ведь можно передавать не x-www-form-urlencoded (т.е. не параметры), а обычный текстовый или бинарный контент, который потом можно будет прочитать через $HTTP_RAW_POST_DATA.

Для этого устанавливаем Content-type text/xml или application/octet-stream, там же устанавливаем charset=«windows-1251».

Засовываем в функцию send() строку нужной кодировки. (Prototype.js оборачивает этот вызов конструкцией new Ajax.Request(...)).

И что потом… А он (объект класса XMLHttpRequest) переводит эту строку в UTF-8, в какой бы кодировке она не была. Так написано в документации W3C. И он реально это делает.

Выводы:

2. Можно передавать строки как бы «в любых других кодировках», если нелатинские символы
при этом за-escape-ены.

3. В JavaScript существует 3 функции, которые escape-ят нелатинские символы:
escape(), encodeURI() и encodeURIComponent().

Первая переводит в кривой Unicode. Вторые две в UTF-8.

Можно написать свои функции, которые будут генерировать escape-последовательности любой кодировки. Можно, но не нужно. Т.к. наоборот надо радоваться, что есть такие вот функции, которые переводят текст любой кодировки в UTF-8. Это черезвычайно прекрасный факт. Схема при которой все xhtml страницы работают на windows-1251, ajax с сервера клиенту кидает windows-1251, а ajax с клиента серверу кидает UTF-8 абсолютна приемлема и используется на большинстве ресурсов .

Просто не надо забывать использовать iconv как было описано ниже. А для того, чтобы сервер отдавал яваскрипту JSON (или что там у вас) в правильной кодировке (т.е. в такой же кодировке, в которой отдаются все xhtml страницы) просто в начале вашего ajax.php пропишите заголовок:

Header("Content-type: text/html; charset=windows-1251");

И всё будет ок.

На последок немного субъективного мнения:

Используйте jQuery, любите людей, дарите подарки.

Вот уже полтора года в draft-ах пылился пост о надуманности проблем с кодировками и т.н. AJAX-ом.
Каждый раз, когда на форумах всплывали вопросы подобного характера, хотелось дать ссылку, на всякий всплеск заходов на блог по запросам “кодировка, ajax, проблема” хотелось его опубликовать, но мне казалось, что пост ещё не закончен, надо ещё чуть-чуть дописать…
Но вот буквально сегодня появился удивительно похожий пост – ajax, cp1251 . Похожий по содержанию, но совершенно противоположный по смыслу.
Посему свой черновичок я решил удалить, а поведать свою “истину” в форме критики совета fxposter-а.

Ни для кого ни секрет, что кодировкой получаемых через Ajax данных по-умолчанию принимается UTF-8.

На самом деле это секрет. Для многих секрет. И многие не понимают почему это так.
Внутреннее представление строк (и регулярных выражений) в JavaScript для всех не-ASCII последовательностей как раз UTF-8.
Отсюда и проистекает т.н. “проблема” – если кодировка не указана явно и используется нелатиница, она будет интерпретирована как utf-8 последовательность.

Update 29.11 Свежий воздух и Давид Мзареулян остудили пыл, поэтому спешу уточнить о чём именно будет идти речь ниже.
Итак – у вас есть некий ресурс в однобайтовой кодировке (к гадалке не ходи это будет windows-1251) и вы озаботились освоить новый buzzword по имени AJAX. Немного почитав, вы делаете первые робкие шаги в этом направлении и тут же наступаете на “детские грабли”, а затем, немного отдышавшись, мчитесь на форумы с криком о помощи. И вам эту помощь окажут – переделай мол, свой ресурс на utf-8… Конечно-конечно скажете вы и пойдёте переделывать…
Я же хочу остеречь от таких опрометчивых шагов.

Cтандартное решение, которое наперебой советуют все – “используй utf-8 и нет проблем”.

И советчики правы – проблем действительно не будет.

Просто трафик увеличится “вдвое”. Те же данные, тот же результат, а трафика “в два раза” больше. Ага?

Что вы там говорите насчёт порошка?!?

Если вам этот фактор кажется мало***щим, то на этом чтение надо прекратить и начать переделывать свой проект на использование UTF-X,
остальным же оставлю несколько рецептов, которые помогут избежать проблем при использовании однобайтовых кодировок в т.н. AJAX-приложениях:

  • Первое, оно же главное – ВСЕГДА указывайте кодировку контента. В любом ответе сервера с текстовым контентом обязан быть заголовок Content-Type: your/type; charset=your-charset .
    Дешевле всего это сделать, настроив сервер (например в php через default_charset)
  • Указывайте charset при включении javascript в тело документа ()
  • Указывайте ПРАВИЛЬНЫЙ charset

    предварительно установив соответствующий заголовок – “Content-Type: text/html; charset=cp1251”

    В данном конкретном взятом за жопу случае fxposter сам себе злобный буратина.

    Any registered IANA charset may be used, but UTF-8 is preferred.

    Ну нету среди any registered кодировки с названием cp1251…

Для полноты картины приведу пару проблемных моментов, с которыми столкнуться прийдётся:

  • Не позволяйте AJAX-ответам, которые содержат “нелатиницу” оставаться в кеше браузера (при 304 Not Modified ответ поднимется из кеша, но в качестве charset “некоторые браузеры” используют utf-8)
  • Этим правилом НАГЛО пользуются производители различных библиотек для json_code, но браузерам (как мы выяснили ранее) главное кодировку указать, а там всё разрулится.
    Отсюда и “проблема” – кодировать данные в JSON нужно вручную, распространнёные библиотечные функции на входе ожидают utf-8.

Мораль сей басни я жду от вас в комментариях.

AJAX и проблемы с кодировкой