用Java编码URL查询参数


108

如何在Java中将查询参数编码为URL?我知道,这似乎是一个显而易见且已经提出的问题。

我不确定有两个微妙之处:

  1. 网址上的空格应该编码为“ +”还是“%20”?在chrome中,如果我输入“ http://google.com/foo=?bar me”,则chrome会将其更改为使用%20进行编码
  2. 是否有必要/正确将冒号“:”编码为%3B?Chrome没有。

笔记:

  • java.net.URLEncoder.encode似乎不起作用,似乎是为了对要编码的数据进行表单提交。例如,它将空格编码为,+而不是%20,并编码不必要的冒号。
  • java.net.URI 不编码查询参数


2
尽管大多数人期望application/x-www-form-urlencoded键/值对,但查询部分的结构取决于服务器。详情请参阅这里:legalargumentexception.blogspot.com/2009/12/…–
McDowell

Answers:


127

java.net.URLEncoder.encode(String s, String encoding)也可以提供帮助。它遵循HTML表单编码application/x-www-form-urlencoded

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

另一方面,百分比编码(也称为URL编码)使用编码空间%20。冒号是保留字符,因此:在编码后仍将保留冒号。


3
我提到过,我认为URL编码不是这样,而是编码要通过表单提交的数据。注释?
亚历克斯·布莱克

这是因为URLEncoder符合application/x-www-form-urlencodedMIME格式(这是有效的HTML表单编码)。我假设这不是您想要的。
Buhake Sindi'3

6
我最终使用URLEncoder.encode并将“ +”替换为“%20”
Alex Black

2
它将斜杠编码为“%2F”,是否不应该将URL斜杠保留原样?
golimar

6
@golimar不,不应该。应该只给它参数值,而不是整个URL。考虑例子http://example.com/?url=http://example.com/?q=c&sort=name。是否应该编码&sort=name?无法从URL区分价值。这就是为什么首先需要值编码的确切原因。
Pijusn 2014年

15

编辑:URIUtil在更新的版本中不再可用,在Java上更好的答案-编码URL或Sindi先生在此线程中。


URIUtilApache httpclient的确很有用,尽管有一些替代方法

URIUtil.encodeQuery(url);

例如,它将空格编码为“ +”而不是“%20”

两者在正确的背景下都是完全有效的。尽管如果您确实更喜欢,则可以发出字符串替换。


我将不得不同意。使用HttpClient,您会更加快乐。
DaShaun 2011年

看起来很有前途,偶然有联系吗?我正在谷歌搜索,但发现了很多。
亚历克斯·布莱克


@Alex,嗯,这很烦人,我一直使用该例程取得了不错的效果。一种想法是从3版本中获取源代码,因为他们现在显然不想再维护它了。
JohanSjöberg

1
URIUtil.encodeWithinQuery您将使用编码单个查询参数的方式进行编码,这就是原始问题似乎在询问的内容。
Jesse Glick 2014年

13

不幸的是,URLEncoder.encode()无法产生有效的百分比编码(如RFC 3986中所指定)。

URLEncoder.encode()可以对所有内容进行正确编码,除了将空格编码为“ +”之外。我只能找到的所有Java URI编码器都只公开用于对查询,片段,路径部分等进行编码的公共方法-但不公开“原始”编码。不幸的是,由于片段和查询被允许将空间编码为+,因此我们不想使用它们。路径已正确编码,但首先被“规范化”,因此我们也不能将其用于“通用”编码。

我能想到的最佳解决方案:

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

如果replaceAll()对您来说太慢,我想替代方法是滚动您自己的编码器...

编辑:我首先在这里有此代码不正确编码“?”,“&”,“ =”:

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

+是对空格的完美有效编码。
劳伦斯·多尔

@LawrenceDol是真的,但有时+可能会被错误地解释-看看C#blogs.msdn.microsoft.com
yangxind/2006/11/

这个。我将各种替代方案与Javascript的encodeURIComponent方法输出进行了比较,这是我尝试的替代方案(带有空格,土耳其语和德语特殊字符的查询)的唯一完全匹配。
UtkuÖzdemir17年

8

尽管这样做不是违法的,但不必在查询中将冒号编码为%3B。

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

似乎还只有百分号编码的空格有效,因为我怀疑空格是ALPHA还是DIGIT

放眼URI规范的更多细节。


但是,这样做可以更改URI的含义,因为查询字符串的解释取决于服务器。如果您要生成application/x-www-form-urlencoded查询字符串,则两者都可以。如果要修复用户键入/粘贴的URL,:则应单独保留。
tc。

@tc。您是正确的,如果将冒号用作通用定界符(RFC第12页);但是,如果未将其用作通用定界符,则两种编码应相同地解析。
Edwin Buck

您还必须小心,因为URL并不是URI的真正子集:adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent

5

内置的Java URLEncoder正在执行预期的操作,您应该使用它。

A“+”或“%20” 在一个URL一个空格字符替换有效。任一个都会起作用。

应该将“:” 编码,因为它是分隔符。即http:// fooftp:// bar。特定浏览器可以在未编码时就可以处理它的事实并不能使其正确。您应该对它们进行编码。

作为一种好的做法,请确保使用采用字符编码参数的方法。UTF-8通常在此处使用,但是您应该明确提供它。

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

5
+只是空间中的代表application/x-www-form-urlencoded; 即使限于HTTP,也不能保证它能正常工作。类似地,:是有效的在查询字符串不应该被转换到%3B; 服务器可以选择以不同的方式解释它们。
tc。

1
这种方法也编码整个URL斜线和其他字符,这是部分如http://http%3A%2F%2F这是不正确的
为了克拉

2
@ToKra,您不应该对该http://部分进行编码。该方法用于查询参数和编码的表单数据。但是,如果您希望将另一个网站的URL作为查询参数传递,则您希望对其进行编码,以避免混淆URL解析器。
beldaz '16

@tc我对w3.org/TR/html4/interact/forms.html#h-17.13.3.3的阅读是,所有GET表单数据都被编码为application/x-www-form-urlencoded内容类型。这不是说必须适用于HTTP吗?
beldaz '16

0

如果您的网址中只有空格问题。我用下面的代码,它工作正常

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

例如:url是

www.xyz.com?para=hello先生

那么muUrl的输出是

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


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

我观察到Datetime(时间戳)URLEncoder.encode(param,"UTF-8")不起作用的情况 。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.