URI编码的URL将“%3D”更改为“%253D”

我在编写URI的URL时遇到问题:

mUrl = "A string url that needs to be encoded for use in a new HttpGet()"; URL url = new URL(mUrl); URI uri = new URI(url.getProtocol(), url.getAuthority(), url.getPath(), url.getQuery(), null); 

这不符合我对以下URL的期望:

传入字符串:

http://m.bloomingdales.com/img?url=http%3A%2F%2Fimages.bloomingdales.com%2Fis%2Fimage%2FBLM%2Fproducts%2F3%2Foptimized%2F1140443_fpx.tif%3Fwid%3D52%26qlt%3D90% 2C0%26layer%3Dcomp%26op_sharpen%3D0%26resMode%3Dsharp2%26op_usm%3D0.7%2C1.0%2C0.5%2C0%26fmt%3Djpeg&TTL = 30D

出来是:

http://m.bloomingdales.com/img?url=http%253A%252F%252Fimages.bloomingdales.com%252Fis%252Fimage%252FBLM%252Fproducts%252F3%252Foptimized%252F1140443_fpx.tif%253Fwid%253D52%2526qlt%253D90% 252C0%2526layer%253Dcomp%2526op_sharpen%253D0%2526resMode%253Dsharp2%2526op_usm%253D0.7%252C1.0%252C0.5%252C0%2526fmt%253Djpeg&TTL = 30D

哪个坏了。 例如, %3D变成%253D它似乎对字符串中的%已经做了一些神秘的事情。

发生了什么事,我在这里做错了什么?

您首先将(已经转义的)字符串放入URL类中。 这并没有逃脱任何事情。 然后你将拉出URL各个部分,这些部分返回它们而不进行任何进一步的处理(因此 – 它们仍然被转义,因为当你把它们放入时它们被转义)。 最后,使用多参数构造函数将这些部分放入URI类中。 此构造函数被指定为使用百分比对URI组件进行编码。

因此,在该最后步骤中,例如,“ : ”变为“ %3A ”(好),“ %3A ”变为“ %253A ”(差)。 由于您要放入已编码*的URL,因此您不希望再次对它们进行编码。

因此, URI的单参数构造函数是您的朋友。 它不会逃避任何事情,并要求您传递预先转义的字符串。 因此,您根本不需要URL

 mUrl = "A string url is already percent-encoded for use in a new HttpGet()"; URI uri = new URI(mUrl); 

*唯一的问题是,如果您的url有时不是百分比编码的,有时它们是。 那你有一个更大的问题。 您需要确定您的程序是从一个始终编码的URL开始,还是需要编码的URL。

请注意,不存在未进行百分比编码的完整URL。 例如,您无法获取完整的url“ http://example.com/bob&co ”并以某种方式将其转换为正确编码的url“ http://example.com/bob%26co ” – 您怎么能告诉语法(不应该被转义)和字符(应该)之间的区别? 这就是URI的单参数forms要求字符串已经转义的原因。 如果你有非转义字符串,你需要将它们插入完整的URL语法之前对它们进行百分比编码,这就是URI的多参数构造函数可以帮助你做的事情。

编辑:我错过了原始代码丢弃片段的事实。 如果要删除URL的片段(或任何其他部分),可以按上述方式构造URI ,然后根据需要拉出所有部分(它们将被解码为常规字符串),然后将它们传递回URI多参数构造函数(它们将被重新编码为URI组件):

 uri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), null) // Remove fragment 

URL类在解析URL时没有解码%-sequences,但URI类正在对它们进行编码(再次)。 使用URI来解析URL字符串。

的Javadoc:

http://download.oracle.com/javase/6/docs/api/java/net/URL.html

URL类本身不会根据RFC2396中定义的转义机制对任何URL组件进行编码或解码 。 调用者负责编码在调用URL之前需要转义的任何字段,以及解码从URL返回的任何转义字段。 此外,由于URL不了解URL转义,因此它无法识别同一URL的编码或解码forms之间的等效性。 例如,两个url:

 http://foo.com/hello world/ and http://foo.com/hello%20world 

被认为不相等。 注意,URI类确实在某些情况下执行其组件字段的转义。

管理URL编码和解码的推荐方法是使用URI ,并使用toURI()和URI.toURL()在这两个类之间进行转换。

%3d表示 – > = (等于)

%253D – > = (等于)十进制6hex(字节)3D

CGI的%253Dhex指示符: %3D

这里发生的是来自第一个URL的%符号被转义,这意味着它们在输出中变为%25 。 您需要采取预防措施,以便您的脚本只能转义字母数字字符,以及一些符号 – 但尚未转义字符。

这些是需要逃避的一些角色:

 < > " ! # $ ' ( ) * , - . / : ; @ [ \ ] ^ _ ` { | } ~ 

其余的,如=%& ,以及字母数字字符,则不会。