Кодування параметрів запиту URL в Java


108

Як один кодує параметри запиту, щоб перейти по URL на Java? Я знаю, це здається очевидним і вже заданим питанням.

Є дві тонкощі, в яких я не впевнений:

  1. Чи повинні пробіли кодуватися в URL-адресі як "+" або як "% 20"? У хромі, якщо я набираю "http://google.com/foo=?bar me", хром змінює його для кодування на% 20
  2. Чи потрібно / правильно кодувати двокрапки ":" як% 3B? Chrome ні.

Примітки:

  • java.net.URLEncoder.encodeСхоже, це не працює, здається, що для кодування даних надсилається форма. Наприклад, він кодує простір як +замість %20, а кодує двокрапку, яка не потрібна.
  • java.net.URI не кодує параметри запиту

Це питання виглядає корисним: stackoverflow.com/questions/444112/…
Alex Black

2
структура частини запиту залежить від сервера, хоча більшість очікує application/x-www-form-urlencodedпар ключів / значень. Дивіться тут докладніше: illegalargumentexception.blogspot.com/2009/12/…
McDowell

Відповіді:


127

java.net.URLEncoder.encode(String s, String encoding)може також допомогти. З цього випливає кодування HTML-форми application/x-www-form-urlencoded.

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

З іншого боку, кодування Percent (також відоме як кодування URL ) кодує простір %20. Двокрапка є зарезервованим символом, тому :залишається двокрапкою після кодування.


3
Я згадував, що не думав, що це кодування URL, а він кодує дані, що надсилаються через форму. коментарі?
Алекс Чорний

Це тому, що URLEncoderвін відповідає application/x-www-form-urlencodedформату MIME (що є дійсним кодуванням HTML-форми). Я припускаю, що це не те, що ви шукаєте.
Buhake Sindi

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

15

EDIT: URIUtilбільше не доступний в останніх версіях, краще відповідь на URL-кодуванні Java - або містером Сінді в цій темі.


URIUtilhttp: // Apache httpclient дуже корисний, хоча є й інші варіанти

URIUtil.encodeQuery(url);

Наприклад, він кодує простір як "+" замість "% 20"

Обидва цілком справедливі в правильному контексті . Хоча якщо ви дійсно вважаєте за краще, ви можете випустити заміну рядка


Я мав би погодитися. Використовуйте HttpClient, ви будете набагато щасливішими.
DaShaun

Це виглядає багатообіцяюче, отримавши посилання випадково? Я гуглю, але знаходжу багатьох.
Алекс Чорний

1
Цей метод, здається, не присутній у HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Алекс Чорний

@ Алекс, хм, це дратує, я завжди використовував цю процедуру з хорошими результатами. Одна з ідей - схопити вихідний код з 3-го випуску, оскільки вони, очевидно, більше не хочуть підтримувати його.
Йохан Шьоберг

1
URIUtil.encodeWithinQueryце те, що ви використовували б кодувати індивідуальний параметр запиту, який, здавалося, задає початкове питання.
Джессі Глік

13

На жаль, URLEncoder.encode () не виробляє дійсних відсоткових кодувань (як зазначено в RFC 3986 ).

URLEncoder.encode () кодує все просто чудово, за винятком місця, закодованого до "+". Усі кодери Java URI, які я міг знайти, розкривають лише загальнодоступні методи кодування запиту, фрагмента, частини шляху тощо - але не піддають "необробленому" кодуванню. Це прикро, оскільки фрагментам та запитам дозволено кодувати простір до +, тому ми не хочемо їх використовувати. Шлях кодується належним чином, але спочатку "нормалізується", тому ми також не можемо використовувати його для "загального" кодування.

Найкраще рішення, яке я міг придумати:

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

Якщо replaceAll()занадто повільно для вас, я думаю, альтернативою є згортання власного кодера ...

EDIT: Спершу у мене був цей код, який не кодує "?", "&", "=" Належним чином:

//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/08/…
Lu55

Це. Я порівнював різні альтернативи з encodeURIComponentвиведенням методу Javascript , і це був єдиний точний збіг для тих, що я намагався (запити з пробілами, спеціальні символи турецької та німецької мов).
Utku Özdemir

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    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Здається також, що пробіли, кодовані лише відсотками, дійсні, оскільки я сумніваюся, що простір - це АЛЬФА чи ЦИФР

див. специфікацію URI для отримання більш детальної інформації.


Але це може змінити значення URI, оскільки інтерпретація рядка запиту залежить від сервера. Якщо ви створюєте application/x-www-form-urlencodedрядок запиту, або добре. Якщо ви налаштовуєте URL-адресу, яку ввів / вставив користувач, її :слід залишити в спокої.
тс.

@tc. Ви маєте рацію, якщо двокрапка використовується як загальний роздільник (стор. 12 RFC); однак, якщо він не використовується як загальний роздільник, то обидва кодування повинні вирішуватися однаково.
Едвін Бак

Ви також повинні бути обережними, оскільки URL-адреси насправді не є підмножиною URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Адам Гент

5

Вбудований в Java URLEncoder робить те, що належить, і ви повинні ним користуватися.

"+" Або "% 20" - це обидві заміни символу пробілу в URL-адресі. Або один буде працювати.

A ":" має бути закодовано, оскільки це розділовий символ. тобто http: // foo або ftp: // bar . Той факт, що певний браузер може працювати з ним, коли він не закодований, не робить його правильним. Ви повинні їх кодувати.

Що стосується належної практики, обов'язково використовуйте метод, який приймає параметр кодування символів. Там, як правило, використовується UTF-8, але ви повинні надавати його чітко.

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

5
+є лише поданням простору в application/x-www-form-urlencoded; він не гарантовано працює навіть при обмеженні HTTP. Аналогічно, :дійсний у рядку запиту і не повинен бути перетворений %3B; сервер може вибрати їх інтерпретувати по-різному.
тс.

1
цей метод також кодує цілі косої коси URL-адреси та інших символів, які є частиною, наприклад, http://до http%3A%2F%2Fякої невірно
До

2
@ToKra ви не повинні кодувати http://частину. Метод призначений для параметрів запиту та кодованих даних форми. Якщо ви хотіли передати URL-адресу іншого веб-сайту як параметр запиту, ТОГО ви хочете кодувати його, щоб не плутати URL-аналізатор.
белдаз

@tc Моє читання w3.org/TR/html4/interact/forms.html#h-17.13.3.3 полягає в тому, що всі дані форми GET кодуються як application/x-www-form-urlencodedтип вмісту. Чи це не означає, що повинен працювати для HTTP?
beldaz

0

якщо у вас є лише проблема з простором у URL-адресі. Я використовував код нижче, і він працює добре

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 (Timestamp) URLEncoder.encode(param,"UTF-8")не працює.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.