2009-04-22 13 views
40

Esiste un Delphi equivalente del metodo di questo .net:Funzione di codifica URL standard?

Url.UrlEncode()

Nota
non ho lavorato con Delphi per diversi anni. Mentre leggo le risposte, noto che ci sono diverse osservazioni e alternative alla risposta correntemente contrassegnata. Non ho avuto l'opportunità di testarli quindi sto basando la mia risposta sul più upvoted.
Per il tuo bene, controlla le risposte successive e dopo aver deciso di aumentare la risposta migliore in modo che tutti possano beneficiare della tua esperienza.

risposta

91

Guardate unità IdURI indy, ha due metodi statici della classe TIdURI per codifica/decodifica l'URL.

uses 
    IdURI; 

.. 
begin 
    S := TIdURI.URLEncode(str); 
// 
    S := TIdURI.URLDecode(str); 
end; 
+6

boris, dai, accetta questa risposta, ho appena dato un punto per essere totalmente utile :) –

+0

Bello, non lo sapevo. Molto utile. –

+3

@Peter Heh, non ho controllato questa domanda perché non sto più lavorando con Delphi. Ma qui vai ugualmente;) –

3

AFAIK è necessario creare il proprio.

Ecco un esempio.

+1

Siamo spiacenti, ma questo non è corretto, controllare le altre risposte. –

+1

Sono stato corretto. –

13

Un'altra opzione è quella di utilizzare la libreria Synapse che ha un semplice metodo di codifica URL (così come molti altri) nell'unità SynaCode.

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

In un ambiente non dotnet, l'unità Wininet fornisce l'accesso alla funzione WinHTTP codifica di Windows': InternetCanonicalizeUrl

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; 

Da Indy.


Comunque Indy non funziona correttamente in modo avete bisogno di vedere questo articolo:
http://marc.durdin.net/2012/07/indy-tiduripathencode-urlencode-and.html

+8

Altar e Marc Durdin hanno ragione. TIdURI è rotto. Unità REST.Utils fornisce una funzione, URIEncode, che funziona correttamente. –

12

mi sono fatto questa funzione per codificare tutto tranne personaggi veramente sicuro. Soprattutto ho avuto problemi con +. Tieni presente che non puoi codificare l'intero URL con questa funzione, ma devi includere le parti che non desideri avere un significato speciale, in genere i valori delle variabili.

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; 
+0

Questa dovrebbe essere la risposta accettata. (non sono sicuro di come gestisca UTF-8) –

+0

Ha problemi con i caratteri Unicode. per esempio. % 633% 6CC% 628 è il risultato della stringa unicode 'سیب' verrà decodificato in 'c3lCb8' – Mahoor13

+0

Ottima risposta. Sicuramente, questa e tutte le soluzioni codificate personalizzate in questa pagina dovrebbero codificare solo i personaggi pericolosi, piuttosto che escludere i personaggi sicuri. Solo lo spazio e i caratteri che hanno un significato speciale negli URI devono essere codificati. Per esempio. [Emb DokWiki] (http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.NetEncoding.TURLEncoding) dice "TURLEncoding codifica solo spazi (come più segni: +) e i seguenti caratteri di codifica URL riservati:;: & = +, /?% # []." – DaveBoltman

16

altro modo semplice per farlo è quello di utilizzare la funzione HTTPEncode nell'unità HTTPApp - molto approssimativamente

Uses 
    HTTPApp; 

function URLEncode(const s : string) : string; 
begin 
    result := HTTPEncode(s); 
end 
2

ero anche affrontando lo stesso problema (Delphi 4).

ho risolto il problema usando sotto la funzione menzionato:

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; 

fonte: Java source code

5

Nelle recenti versioni di Delphi (testato con XE5), utilizzare la funzione URIEncode nell'unità REST.Utils.

3

Ho fatto la mia propria funzione. Converte gli spazi in% 20, non in segno più. Era necessario convertire il percorso del file locale in percorso per browser (con prefisso file: ///). Il più importante è che gestisce le stringhe UTF-8. È stato ispirato dalla soluzione di Radek Hladik di cui sopra.

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

Oh, è stato testato in Lazarus, ma dovrebbe funzionare anche in Delphi 2010+. –

0

TIdUri o HTTPEncode ha problemi con caratteri unicode. La funzione seguente farà la codifica corretta per te.

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

    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;