Стандартная функция кодирования URL?

40

Есть ли эквивалент Delphi этого метода .net:

Url.UrlEncode()

Примечание
Я не работал с Delphi уже несколько лет. Когда я прочитал ответы, я заметил, что есть несколько замечаний и альтернатив в ответ на текущий ответ. У меня не было возможности проверить их, поэтому я основываю свой ответ на наиболее употребимых. Ради себя, проверьте ответы на более поздние и после принятия решения о повышении эффективности ответа, чтобы каждый мог воспользоваться вашим опытом.

Теги:

12 ответов

94
Лучший ответ

Посмотрите на единицу idURI, у него есть два статических метода в классе TIdURI для кодирования/декодирования URL.

uses
  IdURI;

..
begin
  S := TIdURI.URLEncode(str);
//
  S := TIdURI.URLDecode(str);
end;
  • 6
    Борис, давай, прими этот ответ, я просто дал ему точку зрения, чтобы быть полностью полезным :)
  • 0
    Здорово, я этого не знал. Очень полезно.
Показать ещё 5 комментариев
15

Еще один простой способ сделать это - использовать функцию HTTPEncode в модуле HTTPApp - очень грубо

Uses 
  HTTPApp;

function URLEncode(const s : string) : string;
begin
  result := HTTPEncode(s);
end
13
class function TIdURI.ParamsEncode(const ASrc: string): string;
var
  i: Integer;
const
  UnsafeChars = '*#%<> []';  {do not localize}
begin
  Result := '';    {Do not Localize}
  for i := 1 to Length(ASrc) do
  begin
    if CharIsInSet(ASrc, i, UnsafeChars) or (not CharIsInSet(ASrc, i, CharRange(#33,#128))) then begin {do not localize}
      Result := Result + '%' + IntToHex(Ord(ASrc[i]), 2);  {do not localize}
    end else begin
      Result := Result + ASrc[i];
    end;
  end;
end;

От Indy.


В любом случае Indy не работает должным образом, поэтому ВАМ НУЖНО СМОТРЕТЬ ЭТУ СТАТЬЮ:
http://marc.durdin.net/2012/07/indy-tiduripathencode-urlencode-and.html

  • 8
    Алтарь и Марк Дурдин правы. ТИДУРИ сломан. Модуль REST.Utils предоставляет функцию URIEncode, которая работает правильно.
  • 1
    К вашему сведению, приведенный выше код является СТАРЫМ. Это уже не то, TIdURI.ParamsEncode() выглядит TIdURI.ParamsEncode() . В последней версии UnsafeChars содержит гораздо больше символов, Unicode кодируется правильно, а ранее существующие последовательности %HH не кодируются дважды.
13

Другим вариантом является использование библиотеки Synapse, которая имеет простой метод кодирования URL (как и многие другие) в SynaCode.

uses
  SynaCode;
..
begin
  s := EncodeUrl( str );
//
  s := DecodeUrl( str );
end;
12

Я сделал себе эту функцию для кодирования всего, кроме действительно безопасных символов. Особенно у меня были проблемы с+. Имейте в виду, что вы не можете кодировать весь URL с помощью этой функции, но вам нужно encdoe части, которые вы не хотите иметь особого значения, как правило, значения переменных.

function MyEncodeUrl(source:string):string;
 var i:integer;
 begin
   result := '';
   for i := 1 to length(source) do
       if not (source[i] in ['A'..'Z','a'..'z','0','1'..'9','-','_','~','.']) then result := result + '%'+inttohex(ord(source[i]),2) else result := result + source[i];
 end;
  • 1
    Это должен быть принятый ответ. (хотя не уверен, как он справляется с UTF-8)
  • 1
    У него есть проблема с символами Юникода. например. % 633% 6CC% 628 является результатом строки Unicode 'سیب', которая будет декодирована в 'c3lCb8'
Показать ещё 1 комментарий
8

С Delphi xe7 вы можете использовать TNetEncoding.Url.Encode()

6

В среде, отличной от dotnet, модуль Wininet обеспечивает доступ к функции кодирования Windows WinHTTP: InternetCanonicalizeUrl

5

В последних версиях Delphi (протестированных с XE5) используйте функцию URIEncode в модуле REST.Utils.

3

Я сделал свою собственную функцию. Он преобразует пробелы в %20, а не в знак плюса. Необходимо было преобразовать путь локального файла к пути для браузера (с префиксом file:///). Самое главное - это обрабатывать строки UTF-8. Это было вдохновлено решением Радека Хладика выше.

function URLEncode(s: string): string;
var
  i: integer;
  source: PAnsiChar;
begin
  result := '';
  source := pansichar(s);
  for i := 1 to length(source) do
    if not (source[i - 1] in ['A'..'Z', 'a'..'z', '0'..'9', '-', '_', '~', '.', ':', '/']) then
      result := result + '%' + inttohex(ord(source[i - 1]), 2)
    else
      result := result + source[i - 1];
end;       
  • 0
    О, это было проверено в Lazarus, но должно работать и в Delphi 2010+.
3

AFAIK вам нужно сделать свой собственный.

Вот пример.

  • 1
    Извините, но это не правильно, проверьте другие ответы.
  • 1
    Я стою исправлено.
2

Я также столкнулся с той же проблемой (Delphi 4).

Я решил проблему, используя указанную ниже функцию:

function fnstUrlEncodeUTF8(stInput : widestring) : string;
  const
    hex : array[0..255] of string = (
     '%00', '%01', '%02', '%03', '%04', '%05', '%06', '%07',
     '%08', '%09', '%0a', '%0b', '%0c', '%0d', '%0e', '%0f',
     '%10', '%11', '%12', '%13', '%14', '%15', '%16', '%17',
     '%18', '%19', '%1a', '%1b', '%1c', '%1d', '%1e', '%1f',
     '%20', '%21', '%22', '%23', '%24', '%25', '%26', '%27',
     '%28', '%29', '%2a', '%2b', '%2c', '%2d', '%2e', '%2f',
     '%30', '%31', '%32', '%33', '%34', '%35', '%36', '%37',
     '%38', '%39', '%3a', '%3b', '%3c', '%3d', '%3e', '%3f',
     '%40', '%41', '%42', '%43', '%44', '%45', '%46', '%47',
     '%48', '%49', '%4a', '%4b', '%4c', '%4d', '%4e', '%4f',
     '%50', '%51', '%52', '%53', '%54', '%55', '%56', '%57',
     '%58', '%59', '%5a', '%5b', '%5c', '%5d', '%5e', '%5f',
     '%60', '%61', '%62', '%63', '%64', '%65', '%66', '%67',
     '%68', '%69', '%6a', '%6b', '%6c', '%6d', '%6e', '%6f',
     '%70', '%71', '%72', '%73', '%74', '%75', '%76', '%77',
     '%78', '%79', '%7a', '%7b', '%7c', '%7d', '%7e', '%7f',
     '%80', '%81', '%82', '%83', '%84', '%85', '%86', '%87',
     '%88', '%89', '%8a', '%8b', '%8c', '%8d', '%8e', '%8f',
     '%90', '%91', '%92', '%93', '%94', '%95', '%96', '%97',
     '%98', '%99', '%9a', '%9b', '%9c', '%9d', '%9e', '%9f',
     '%a0', '%a1', '%a2', '%a3', '%a4', '%a5', '%a6', '%a7',
     '%a8', '%a9', '%aa', '%ab', '%ac', '%ad', '%ae', '%af',
     '%b0', '%b1', '%b2', '%b3', '%b4', '%b5', '%b6', '%b7',
     '%b8', '%b9', '%ba', '%bb', '%bc', '%bd', '%be', '%bf',
     '%c0', '%c1', '%c2', '%c3', '%c4', '%c5', '%c6', '%c7',
     '%c8', '%c9', '%ca', '%cb', '%cc', '%cd', '%ce', '%cf',
     '%d0', '%d1', '%d2', '%d3', '%d4', '%d5', '%d6', '%d7',
     '%d8', '%d9', '%da', '%db', '%dc', '%dd', '%de', '%df',
     '%e0', '%e1', '%e2', '%e3', '%e4', '%e5', '%e6', '%e7',
     '%e8', '%e9', '%ea', '%eb', '%ec', '%ed', '%ee', '%ef',
     '%f0', '%f1', '%f2', '%f3', '%f4', '%f5', '%f6', '%f7',
     '%f8', '%f9', '%fa', '%fb', '%fc', '%fd', '%fe', '%ff');
 var
   iLen,iIndex : integer;
   stEncoded : string;
   ch : widechar;
 begin
   iLen := Length(stInput);
   stEncoded := '';
   for iIndex := 1 to iLen do
   begin
     ch := stInput[iIndex];
     if (ch >= 'A') and (ch <= 'Z') then
       stEncoded := stEncoded + ch
     else if (ch >= 'a') and (ch <= 'z') then
       stEncoded := stEncoded + ch
     else if (ch >= '0') and (ch <= '9') then
       stEncoded := stEncoded + ch
     else if (ch = ' ') then
       stEncoded := stEncoded + '+'
     else if ((ch = '-') or (ch = '_') or (ch = '.') or (ch = '!') or (ch = '*')
       or (ch = '~') or (ch = '\')  or (ch = '(') or (ch = ')')) then
       stEncoded := stEncoded + ch
     else if (Ord(ch) <= $07F) then
       stEncoded := stEncoded + hex[Ord(ch)]
     else if (Ord(ch) <= $7FF) then
     begin
        stEncoded := stEncoded + hex[$c0 or (Ord(ch) shr 6)];
        stEncoded := stEncoded + hex[$80 or (Ord(ch) and $3F)];
     end
     else
     begin
        stEncoded := stEncoded + hex[$e0 or (Ord(ch) shr 12)];
        stEncoded := stEncoded + hex[$80 or ((Ord(ch) shr 6) and ($3F))];
        stEncoded := stEncoded + hex[$80 or ((Ord(ch)) and ($3F))];
     end;
   end;
   result := (stEncoded);
 end;

источник: исходный код Java

0

TIdUri или HTTPEncode имеет проблемы с символами Unicode. Функция ниже сделает правильное кодирование для вас.

function EncodeURIComponent(const ASrc: string): UTF8String;
const
  HexMap: UTF8String = '0123456789ABCDEF';

  function IsSafeChar(ch: Integer): Boolean;
  begin
    if (ch >= 48) and (ch <= 57) then Result := True    // 0-9
    else if (ch >= 65) and (ch <= 90) then Result := True  // A-Z
    else if (ch >= 97) and (ch <= 122) then Result := True  // a-z
    else if (ch = 33) then Result := True // !
    else if (ch >= 39) and (ch <= 42) then Result := True // '()*
    else if (ch >= 45) and (ch <= 46) then Result := True // -.
    else if (ch = 95) then Result := True // _
    else if (ch = 126) then Result := True // ~
    else Result := False;
  end;
var
  I, J: Integer;
  ASrcUTF8: UTF8String;
begin
  Result := '';    {Do not Localize}

  ASrcUTF8 := UTF8Encode(ASrc);
  // UTF8Encode call not strictly necessary but
  // prevents implicit conversion warning

  I := 1; J := 1;
  SetLength(Result, Length(ASrcUTF8) * 3); // space to %xx encode every byte
  while I <= Length(ASrcUTF8) do
  begin
    if IsSafeChar(Ord(ASrcUTF8[I])) then
    begin
      Result[J] := ASrcUTF8[I];
      Inc(J);
    end
    else if ASrcUTF8[I] = ' ' then
    begin
      Result[J] := '+';
      Inc(J);
    end
    else
    begin
      Result[J] := '%';
      Result[J+1] := HexMap[(Ord(ASrcUTF8[I]) shr 4) + 1];
      Result[J+2] := HexMap[(Ord(ASrcUTF8[I]) and 15) + 1];
      Inc(J,3);
    end;
    Inc(I);
  end;

  SetLength(Result, J-1);
end;
  • 1
    Я считаю, что это правильный кредит для этого кода: marc.durdin.net/2012/07/… И обновленная версия, которая также работает на мобильных платформах: marc.durdin.net/2015/08/an-update-for -encodeuricomponent
  • 1
    Следует также отметить, что в этом коде (как на веб-сайте, откуда он пришел), пробел неправильно закодирован как + . Это не так, как должен работать encodeURIComponent. Вместо этого он должен кодироваться как% 20: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Хотя это исправлено в мобильной версии.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню