Кодировка URL-адреса URI изменяет "%3D " на " %253D"

у меня возникли проблемы с кодированием 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

выходит as:

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 Кажется, что это делает что-то загадочное для %уже в строке.

что происходит и что я делаю неправильно здесь?

4 ответов


вы сначала ставите (уже сбежал) строку URL класса. От этого ничего не ускользает. Тогда вы вытаскиваете разделы URL, который возвращает их без какой-либо дальнейшей обработки (так что -- они все еще экранированы, так как они были экранированы, когда вы их вставили). Наконец, вы помещаете разделы в URI класс, с помощью конструктор с несколькими аргументами. Этот конструктор задается как кодирование компонентов URI с помощью проценты.

поэтому именно на этом последнем этапе, например,":" в "%3A" (хорошо) и "%3A" в "%253A" (плохо). Поскольку вы вводите URL-адреса, которые уже закодированы*, вы не хотите кодировать их снова.

таким образом,конструктор с одним аргументом of URI - твой друг. Он ничего не избегает и требует, чтобы вы передали предварительно экранированную строку. Следовательно, вам не нужно URL at все:

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

*единственная проблема заключается в том, что ваши URL-адреса иногда не закодированы в процентах, а иногда они есть. Тогда у вас проблема посерьезнее. Вам нужно решить, начинается ли ваша программа с URL-адреса, который всегда закодирован, или тот, который должен быть закодирован.

обратите внимание, что есть ничего подобного как полный URL, который не закодирован в процентах. Например, вы не можете взять полный URL "http://example.com/bob&co " и как-то превратить его в правильно закодированный URL-адресу "http://example.com/bob%26co " -- как вы можете сказать разницу между синтаксисом (который не должен быть экранирован) и символами (которые должны)? Вот почему форма одного аргумента URI требует, чтобы строки уже сбежал. Если у вас есть строки без эскапады, вам нужно их кодировать в процентах до вставка их в полный синтаксис URL-адреса, и это то, что конструктор с несколькими аргументами URI поможет вам сделать.

Edit: я пропустил тот факт, что исходный код отбрасывает фрагмент. Если вы хотите удалить фрагмент (или любую другую часть) URL-адреса, вы можете создать URI как указано выше, затем вытащите все детали по мере необходимости (они будут декодируются в регулярные строки), затем передайте их обратно в URI конструктор с несколькими аргументами (где они будут перекодируется как компоненты URI):

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

на URL класс не декодировал % - последовательности при анализе URL-адреса, но URI класс кодирует их (снова). Использовать URI для анализа строки URL.

Javadocs:

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

класс URL сам не кодирует и не декодирует компоненты URL согласно экранируя механизму определенному в RFC2396. Это ответственность вызывающего кодировать любые поля, которые должны быть экранированы до вызова URL, а также декодировать любые экранированные поля, которые возвращаются из URL. Кроме того, поскольку URL-адрес не знает об экранировании URL-адреса, он не распознает эквивалентность между закодированной или декодированной формой того же URL-адреса. Например, два URL:

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

будут считаться не равными друг другу. Обратите внимание, что класс URI выполняет экранирование его поля компонентов при определенных обстоятельствах.

рекомендуемый способ управления кодированием и декодированием URL-адресов-использовать URI, и конвертировать между этими двумя классами с помощью toURI () и URI.toURL().


%в 3D значит--> = (равно)

и

%253D -->= (равно) decimal 6hex (байт) 3D

%253D Хекс индикатор для CGI: %в 3D


то, что здесь происходит, это то, что % знаки из первого URL-адреса экранируются, что означает, что они превращаются в %25 в выходной. Вам нужно принять меры предосторожности, чтобы ваш скрипт избегал только буквенно-цифровых символов, а также некоторых символов - но не уже убежал персонажей.

это некоторые символы, которые нужно избежать:

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

остальное, как =, % и &, и буквенно-цифровые символы, do не.