2009-04-22 49 views
40

Có tương đương Delphi của phương pháp của .net này:Chức năng mã hóa URL chuẩn?

Url.UrlEncode()

Note
Tôi chưa từng làm việc với Delphi trong nhiều năm nay. Khi tôi đọc qua các câu trả lời, tôi nhận thấy rằng có một số nhận xét và lựa chọn thay thế cho câu trả lời hiện đang được đánh dấu. Tôi đã không có cơ hội để kiểm tra chúng vì vậy tôi đang căn cứ vào câu trả lời của tôi về việc được bầu chọn nhiều nhất.
Vì lợi ích của riêng bạn, hãy kiểm tra câu trả lời sau và sau khi quyết định upvote câu trả lời hay nhất để mọi người có thể hưởng lợi từ trải nghiệm của bạn.

Trả lời

91

Nhìn vào đơn vị IdURI indy, nó có hai phương pháp tĩnh trong lớp TIdURI cho Encode/Decode URL.

uses 
    IdURI; 

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

boris, thôi nào, chấp nhận câu trả lời này, tôi chỉ cho nó một điểm để được hoàn toàn hữu ích :) –

+0

Tốt, tôi không biết điều này. Rất hữu ích. –

+3

@Peter Heh, tôi không kiểm tra câu hỏi này vì tôi không làm việc với Delphi nữa. Nhưng ở đây bạn đi anyway;) –

3

AFAIK bạn cần phải tự tạo.

Đây là một ví dụ.

+1

Xin lỗi, nhưng điều này không đúng, hãy kiểm tra các câu trả lời khác. –

+1

Tôi đã sửa. –

13

Một lựa chọn khác là sử dụng thư viện Synapse trong đó có một phương pháp mã hóa URL đơn giản (cũng như nhiều người khác) trong đơn vị SynaCode.

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

Trong một môi trường không DotNet, đơn vị Wininet cung cấp quyền truy cập vào Windows chức năng WinHTTP mã hóa: 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; 

Từ Indy.


Dù sao Indy không hoạt động đúng để bạn cần phải xem ĐIỀU NÀY:
http://marc.durdin.net/2012/07/indy-tiduripathencode-urlencode-and.html

+8

Bàn thờ và Marc Durdin là đúng. TIdURI bị hỏng. Unit REST.Utils cung cấp một hàm, URIEncode, hoạt động đúng. –

12

tôi làm bản thân mình chức năng này để mã hóa tất cả mọi thứ ngoại trừ nhân vật thực sự an toàn. Đặc biệt tôi gặp vấn đề với +. Hãy lưu ý rằng bạn không thể mã hóa toàn bộ URL bằng hàm này nhưng bạn cần phải mã hóa các phần mà bạn không muốn có ý nghĩa đặc biệt, thường là các giá trị của các biến.

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

Đây phải là câu trả lời được chấp nhận. (không chắc chắn làm thế nào nó xử lý UTF-8 mặc dù) –

+0

Nó có vấn đề với unicode charecters. ví dụ. % 633% 6CC% 628 là kết quả của chuỗi unicode 'سیب', nó sẽ được giải mã thành 'c3lCb8' – Mahoor13

+0

Câu trả lời hay. Chắc chắn, điều này và tất cả các giải pháp được mã hóa tùy chỉnh trên trang này chỉ nên mã hóa các ký tự nguy hiểm, thay vì loại trừ các ký tự an toàn. Chỉ không gian và các ký tự có ý nghĩa đặc biệt trong các URI cần phải được mã hóa. Ví dụ. [Emb DokWiki] (http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.NetEncoding.TURLEncoding) nói "TURLEncoding chỉ mã hóa các dấu cách (như dấu cộng: +) và các ký tự mã hóa URL được bảo lưu sau:;: & = +, /?% # []. " – DaveBoltman

16

Một cách đơn giản để làm điều này là để sử dụng chức năng HTTPEncode trong đơn vị HTTPApp - rất gần

Uses 
    HTTPApp; 

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

Tôi cũng đã phải đối mặt với cùng một vấn đề (Delphi 4).

tôi giải quyết vấn đề bằng cách sử dụng dưới đây chức năng đề cập:

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; 

nguồn: Java source code

5

Trong các phiên bản gần đây của Delphi (thử nghiệm với XE5), sử dụng chức năng URIEncode trong đơn vị REST.Utils.

3

Tôi đã thực hiện chức năng của riêng mình. Nó chuyển đổi không gian thành% 20, chứ không phải dấu cộng. Cần chuyển đổi đường dẫn tệp cục bộ thành đường dẫn cho trình duyệt (với tệp: /// prefix). Điều quan trọng nhất là nó xử lý các chuỗi UTF-8. Nó được lấy cảm hứng từ giải pháp của Radek Hladik ở trên.

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

Ồ, nó đã được thử nghiệm ở Lazarus, nhưng cũng nên làm việc trong Delphi 2010+. –

0

TIdUri hoặc HTTPEncode gặp sự cố với các ký tự unicode. Chức năng dưới đây sẽ thực hiện mã hóa chính xác cho bạn.

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;