Mã hóa các tham số truy vấn URL trong Java


108

Làm cách nào để mã hóa các tham số truy vấn để đi đến một url trong Java? Tôi biết, đây dường như là một câu hỏi hiển nhiên và đã được đặt ra.

Có hai điều tinh tế mà tôi không chắc:

  1. Khoảng trắng có nên được mã hóa trên url là "+" hoặc "% 20" không? Trong chrome nếu tôi nhập "http://google.com/foo=?bar me" chrome sẽ chuyển nó thành mã hóa% 20
  2. Có cần / chính xác để mã hóa dấu hai chấm ":" dưới dạng% 3B không? Chrome thì không.

Ghi chú:

  • java.net.URLEncoder.encodedường như không hoạt động, nó có vẻ là để mã hóa dữ liệu được gửi biểu mẫu. Ví dụ: nó mã hóa khoảng trắng +thay vì %20mã hóa dấu hai chấm không cần thiết.
  • java.net.URI không mã hóa các tham số truy vấn

Câu hỏi này có vẻ hữu ích: stackoverflow.com/questions/444112/…
Alex Black,

2
cấu trúc của phần truy vấn phụ thuộc vào máy chủ, mặc dù hầu hết mong đợi application/x-www-form-urlencodedcác cặp khóa / giá trị. Xem ở đây để biết thêm: bất hợp phápargumentexception.blogspot.com/2009/12/
McDowell

Câu trả lời:


127

java.net.URLEncoder.encode(String s, String encoding)cũng có thể giúp. Nó tuân theo mã hóa biểu mẫu HTML application/x-www-form-urlencoded.

URLEncoder.encode(query, "UTF-8");

Mặt khác, Mã hóa phần trăm (còn được gọi là mã hóa URL ) mã hóa không gian với %20. :Dấu hai chấm là một ký tự dành riêng, vì vậy sẽ vẫn là dấu hai chấm, sau khi mã hóa.


3
Tôi đã đề cập rằng tôi không nghĩ rằng điều đó có mã hóa url, thay vào đó nó mã hóa dữ liệu được gửi qua biểu mẫu. bình luận?
Alex Black,

Đó là bởi vì URLEncodernó tuân theo application/x-www-form-urlencodedđịnh dạng MIME (là một mã hóa biểu mẫu HTML hợp lệ). Tôi cho rằng đó không phải là thứ bạn đang tìm kiếm.
Buhake Sindi

6
Tôi đã kết thúc bằng URLEncoder.encode và thay thế "+" với "% 20"
Alex Đen

2
Nó mã hóa các dấu gạch chéo thành "% 2F", nó có nên để lại các dấu gạch chéo URL như chúng không?
golimar,

6
@golimar Không, không nên. Bạn phải chỉ cung cấp cho nó giá trị tham số chứ không phải toàn bộ URL. Hãy xem xét ví dụ http://example.com/?url=http://example.com/?q=c&sort=name. Nó có nên mã hóa &sort=namehay không? Không có cách nào để phân biệt giá trị với URL. Đó là lý do chính xác tại sao bạn cần mã hóa giá trị ngay từ đầu.
Pijusn

15

EDIT: URIUtilkhông còn khả dụng trong các phiên bản gần đây, câu trả lời tốt hơn tại Java - mã hóa URL hoặc của ông Sindi trong chủ đề này.


URIUtilcủa Apache httpclient thực sự hữu ích, mặc dù có một số lựa chọn thay thế

URIUtil.encodeQuery(url);

Ví dụ: nó mã hóa không gian thành "+" thay vì "% 20"

Cả hai đều hoàn toàn hợp lệ trong bối cảnh phù hợp . Mặc dù nếu bạn thực sự thích, bạn có thể đưa ra một chuỗi thay thế.


Tôi sẽ phải đồng ý. Sử dụng HttpClient, bạn sẽ hạnh phúc hơn rất nhiều.
DaShaun

Trông có vẻ hứa hẹn, tình cờ có được một liên kết? Tôi đang truy cập nhưng tìm thấy nhiều.
Alex Black,

1
Phương pháp này dường như không có trong HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Alex Black

@Alex, hmm thật khó chịu, tôi đã luôn sử dụng thói quen đó với kết quả tốt. Một ý tưởng là lấy mã nguồn từ bản phát hành 3 vì bây giờ họ rõ ràng không muốn duy trì nó nữa.
Johan Sjöberg

1
URIUtil.encodeWithinQuerylà những gì bạn sẽ sử dụng mã hóa một tham số truy vấn riêng lẻ, đó là những gì câu hỏi ban đầu dường như đang hỏi.
Jesse Glick vào

13

Rất tiếc, URLEncoder.encode () không tạo mã hóa phần trăm hợp lệ (như được chỉ định trong RFC 3986 ).

URLEncoder.encode () mã hóa mọi thứ tốt, ngoại trừ khoảng trắng được mã hóa thành "+". Tất cả các bộ mã hóa Java URI mà tôi có thể tìm thấy chỉ hiển thị các phương thức công khai để mã hóa các phần truy vấn, phân đoạn, đường dẫn, v.v. - nhưng không hiển thị mã hóa "thô". Điều này thật đáng tiếc vì phân đoạn và truy vấn được phép mã hóa không gian thành +, vì vậy chúng tôi không muốn sử dụng chúng. Đường dẫn được mã hóa đúng cách nhưng được "chuẩn hóa" trước nên chúng tôi cũng không thể sử dụng nó cho mã hóa 'chung chung'.

Giải pháp tốt nhất mà tôi có thể đưa ra:

return URLEncoder.encode(raw, "UTF-8").replaceAll("\\+", "%20");

Nếu replaceAll()quá chậm đối với bạn, tôi đoán giải pháp thay thế là cuộn bộ mã hóa của riêng bạn ...

CHỈNH SỬA: Đầu tiên tôi có mã này ở đây, mã này không mã hóa "?", "&", "=" Đúng cách:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);

+là một mã hóa hoàn toàn hợp lệ của một khoảng trắng.
Lawrence Dol

@LawrenceDol đó là sự thật nhưng đôi khi +có thể được giải thích không chính xác - hãy nhìn vào C # blogs.msdn.microsoft.com/yangxind/2006/11/08/...
Lu55

Điều này. Tôi đã so sánh các lựa chọn thay thế khác nhau với encodeURIComponentđầu ra phương thức của Javascript và đây là kết quả phù hợp chính xác duy nhất cho những lựa chọn tôi đã thử (truy vấn có dấu cách, ký tự đặc biệt tiếng Thổ Nhĩ Kỳ và tiếng Đức).
Utku Özdemir

8

Không cần thiết phải mã hóa dấu hai chấm là% 3B trong truy vấn, mặc dù làm như vậy không phải là bất hợp pháp.

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Có vẻ như chỉ những không gian được mã hóa theo phần trăm mới hợp lệ, vì tôi nghi ngờ rằng không gian đó là ALPHA hoặc DIGIT

xem đặc tả URI để biết thêm chi tiết.


Nhưng làm như vậy có thể thay đổi ý nghĩa của URI, vì việc giải thích chuỗi truy vấn là tùy thuộc vào máy chủ. Nếu bạn đang tạo một application/x-www-form-urlencodedchuỗi truy vấn, thì cũng tốt. Nếu bạn đang sửa một URL mà người dùng đã nhập / dán vào, :hãy để yên.
tc.

@tc. Bạn nói đúng, nếu dấu hai chấm được sử dụng làm dấu phân cách chung (trang 12 của RFC); tuy nhiên, nếu nó không được sử dụng làm dấu phân cách chung, thì cả hai bảng mã sẽ phân giải giống nhau.
Edwin Buck

Bạn cũng phải cẩn thận vì URL không thực sự là một tập hợp con của URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent

5

Bộ mã hóa URLEncoder được xây dựng trong Java đang làm những gì nó phải làm và bạn nên sử dụng nó.

A "+" hoặc "% 20" là cả hai thay thế hợp lệ cho một nhân vật không gian trong một URL. Một trong hai sẽ hoạt động.

Một ":" phải được mã hóa, vì nó là một ký tự phân tách. tức là http: // foo hoặc ftp: // bar . Thực tế là một trình duyệt cụ thể có thể xử lý nó khi nó không được mã hóa không làm cho nó chính xác. Bạn nên mã hóa chúng.

Như một vấn đề thực tiễn tốt, hãy đảm bảo sử dụng phương thức nhận tham số mã hóa ký tự. UTF-8 thường được sử dụng ở đó, nhưng bạn nên cung cấp nó một cách rõ ràng.

URLEncoder.encode(yourUrl, "UTF-8");

5
+chỉ là một đại diện của không gian trong application/x-www-form-urlencoded; nó không được đảm bảo hoạt động ngay cả khi bị giới hạn ở HTTP. Tương tự, :là hợp lệ trong một chuỗi truy vấnkhông được chuyển đổi thành %3B; một máy chủ có thể chọn giải thích chúng theo cách khác nhau.
tc.

1
phương pháp này cũng mã hóa slashes url toàn thể và các nhân vật khác mà là một phần ví dụ http://để http%3A%2F%2Fđó là không đúng
Để Kra

2
@ToKra bạn không phải mã hóa http://phần này. Phương pháp này dành cho các tham số truy vấn và dữ liệu biểu mẫu được mã hóa. Tuy nhiên, nếu bạn muốn chuyển URL của một trang web khác làm tham số truy vấn, THÌ bạn sẽ muốn mã hóa nó để tránh gây nhầm lẫn cho trình phân tích cú pháp URL.
beldaz

@tc Bài đọc của tôi về w3.org/TR/html4/interact/forms.html#h-17.13.3.3 là tất cả dữ liệu biểu mẫu GET đều được mã hóa dưới dạng application/x-www-form-urlencodednội dung. Điều đó không có nghĩa là phải hoạt động cho HTTP?
beldaz

0

nếu bạn chỉ có vấn đề về không gian trong url. Tôi đã sử dụng mã dưới đây và nó hoạt động tốt

String url;
URL myUrl = new URL(url.replace(" ","%20"));

ví dụ: url là

www.xyz.com?para=hello thưa ngài

thì đầu ra của muUrl là

www.xyz.com?para=hello%20sir


0
String param="2019-07-18 19:29:37";
param="%27"+param.trim().replace(" ", "%20")+"%27";

Tôi đã quan sát thấy trong trường hợp Datetime (Dấu thời gian) URLEncoder.encode(param,"UTF-8")không hoạt động.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.