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

2022-09-03 17:02:52

我在将 URL 编码为 URI 时遇到问题:

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

这是怎么回事,我在这里做错了什么?


答案 1

首先将(已转义的)字符串放入类中。这并不能逃脱任何东西。然后,您将拉出 的部分,这将返回它们而无需任何进一步的处理(因此 - 它们仍然被转义,因为它们在您放入时被转义)。最后,使用多参数构造函数将这些部分放入类中。此构造函数指定为使用百分比对 URI 组件进行编码。URLURLURI

因此,例如,在最后一步中,“”变为“”(好),“”变为“”(坏)。由于您输入的是已编码*的 URL,因此您不想再次对其进行编码。:%3A%3A%253A

因此,的单参数构造函数是你的朋友。它不会转义任何内容,并要求您传递预转义字符串。因此,您根本不需要:URIURL

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

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

请注意,没有未进行百分比编码的完整URL。例如,你不能把完整的URL“”以某种方式变成正确编码的URL“”——你怎么能分辨语法(不应该转义)和字符(应该)之间的区别?这就是为什么 的单参数形式要求字符串已经过转义的原因。如果您有未转义的字符串,则需要在将它们插入完整的 URL 语法之前对其进行百分比编码,这就是 多参数构造函数帮助您做到的。http://example.com/bob&cohttp://example.com/bob%26coURIURI

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

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

答案 2

%3d 均值-> = (相等)

%253D --> = (相等) 十进制 6 十六进制(字节) 3D

%253D CGI 的十六进制指示器: %3D