FoxBase!
msgbartop
Блог Oracle разработчика
msgbarbottom
foxbase

04.10.2010 Indy TIdHTTP.POST и русские символы в параметрах запроса

idHTTP.POST

О проблемах и ошибках Indy при работе с национальными кодировками в сети ходят легенды, часто заставляя искать альтернативные компоненты для работы с интернетом. Одна из проблем Indy заключается в невозможности отправить нормальный русский текст методом TIdHTTP.POST. Искать ошибки внутри самой Indy и исправлять их не кажется очень правильным решением, так как все таки компоненты развиваются и есть надежда на то, что ошибки будут исправлены в будущем. В этой статье предлагается решение проблемы отправки русского текста методом POST при помощи компонента TIdHTTP

Стандартный способ использования TIdHTTP.POST состоит в заполнении параметров запроса и отсылки запроса командой:

HTTP.Post(URL,Params);
Где URL - URL запроса, Params - список параметров вида param=value, хранящийся в объекте класса TStringList.
Значения параметров в русской кодировке обычно в Indy отправляются неверно. Indy по умолчанию пытается перекодировать только самому себе понятным образом значения параметров. Это поведение можно отключить, если выставить HTTPOptions:=[], убрав тем самым влияние неправильно работающей опции hoForceEncodeParams. В некоторых случаях это помогает, если предварительно перекодировать передаваемые в параметрах строки. Но помогает далеко не всегда, решения часто получаются локальные и не всегда могут нас устроить.
Решить проблему нам поможет перегруженный метод TIdHTTP.POST, в котором параметры передаются через TStringStreamTStringStream обладает одним замечательным свойством: мы можем выбрать требуемую нам кодировку при создании объекта этого класса. Это и является решением проблемы с русскими символами в 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);
www.foxbase.ru


Смотрите также:



Оставьте свой комментарий

Вы должны быть авторизированны, чтобы оставить комментарий.