О проблемах и ошибках Indy при работе с национальными кодировками в сети ходят легенды, часто заставляя искать альтернативные компоненты для работы с интернетом. Одна из проблем Indy заключается в невозможности отправить нормальный русский текст методом TIdHTTP.POST. Искать ошибки внутри самой Indy и исправлять их не кажется очень правильным решением, так как все таки компоненты развиваются и есть надежда на то, что ошибки будут исправлены в будущем. В этой статье предлагается решение проблемы отправки русского текста методом POST при помощи компонента TIdHTTP.
Стандартный способ использования
TIdHTTP.POST состоит в заполнении параметров запроса и отсылки запроса командой:
Где URL - URL запроса, Params - список параметров вида param=value, хранящийся в объекте класса TStringList.
Значения параметров в русской кодировке обычно в Indy отправляются неверно. Indy по умолчанию пытается перекодировать только самому себе понятным образом значения параметров. Это поведение можно отключить, если выставить HTTPOptions:=[], убрав тем самым влияние неправильно работающей опции hoForceEncodeParams. В некоторых случаях это помогает, если предварительно перекодировать передаваемые в параметрах строки. Но помогает далеко не всегда, решения часто получаются локальные и не всегда могут нас устроить.
Решить проблему нам поможет перегруженный метод TIdHTTP.POST, в котором параметры передаются через TStringStream. TStringStream обладает одним замечательным свойством: мы можем выбрать требуемую нам кодировку при создании объекта этого класса. Это и является решением проблемы с русскими символами в TIdHTTP.POST.
Для начала для
TIdHTTP обязательно необходимо выставить свойство
ContentType:
idHTTP.Request.ContentType:='application/x-www-form-urlencoded';
Если наши параметры хранятся в TStringList, то сформируем строку параметров например так:
for i := 0 to FParams.Count - 1 do
begin
s:=s+Params.Names[i]+'='+Params.Values[Params.Names[i]];
if i<>Params.Count - 1 then s:=s+'&';
end;
POST запрос выполняется следующим образом:
ss:=TStringStream.Create(s,1251);
html:=http.Post(URL,ss);
Как понятно, в этом примере использована кодировка Windows-1251
Если же нам необходимо передать параметры в кодировке
UTF8, то для этого потребуется функция перекодирования текста. Например такая:
uses Windows, Character, IdGlobal, IdGlobalProtocols
function EncodeString(str: string): string;
const
UnsafeChars = '*#%<> []';
var
I: Integer;
J, Len: Integer;
U: UTF8String;
begin
Result := '';
I := 1;
while I <= Length(str) do
if CharIsInSet(str, I, UnsafeChars) or (not CharIsInSet(str, I, CharRange(#33,Char(128)))) then
begin
TCharacter.ConvertToUtf32(str, I, Len );
U := UTF8String(Copy(str, I, Len));
Inc(I, Len);
for J := 1 to Length(U) do begin
Result := Result + '%' + IntToHex(Ord(U[J]), 2);
end;
end else begin
Result := Result + str[I];
Inc(I);
end;
end;
POST запрос при этом будет выглядеть следующим образом:
for i := 0 to FParams.Count - 1 do
begin
s:=s+Params.Names[i]+'='+EncodeString(Params.Values[Params.Names[i]]);
if i<>Params.Count - 1 then s:=s+'&';
end;
ss:=TStringStream.Create(s,CP_UTF8);
html:=http.Post(URL,ss);
Смотрите также:
Оставьте свой комментарий
Вы должны быть авторизированны, чтобы оставить комментарий.