Java URL кодирование параметров строки запроса

Скажи, что у меня есть URL

http://example.com/query?q=

и у меня есть запрос, введенный пользователем, например:

случайное слово £ 500 банк $

Я хочу, чтобы результат был правильно закодированным URL:

http://example.com/query?q=random%20word%20%A3500%20bank%20%24

Как лучше всего этого добиться? Я пыталсяURLEncoder и создание объектов URI / URL, но ни один из них не получается совершенно правильным.

 Mark Elliot28 мая 2012 г., 16:12
Что ты имеешь в виду под словом "ни один из них не подходит"?
 ND2717 июн. 2014 г., 18:31
Я использовал URI.create и заменил пробелы на + в строке запроса. На сайте клиента он преобразовал + обратно в пробелы, когда я выбрал строки запроса. Это сработало для меня.
 jschnasse12 апр. 2018 г., 15:46
Почему ты ожидаешь, что $ будет кодироваться в процентах?

Ответы на вопрос(9)

роения и кодирования параметров запроса -

С использованием HttpComponents 4.x - URLEncodedUtils

Для использования HttpClient 3.x - EncodingUtil

Используйте это: URLEncoder.encode (query, StandardCharsets.UTF_8.displayName ()); или это: URLEncoder.encode (запрос, "UTF-8");

Вы можете использовать следующий код.

String encodedUrl1 = UriUtils.encodeQuery(query, "UTF-8");//not change 
String encodedUrl2 = URLEncoder.encode(query, "UTF-8");//changed
String encodedUrl3 = URLEncoder.encode(query, StandardCharsets.UTF_8.displayName());//changed

System.out.println("url1 " + encodedUrl1 + "\n" + "url2=" + encodedUrl2 + "\n" + "url3=" + encodedUrl3);
 user20742113 февр. 2018 г., 02:40
Не верно. Вы должны кодировать имена параметров и значения отдельно. Кодирование всей строки запроса также будет кодировать= а также& разделители, что не правильно.

товых случаев, предоставленныхWeb Plattform Tes, ts):

0 Проверьте, если URL уже закодирован. Замените '+' кодированные пробелы на '% 20' кодированные пробелы.

1. Разделить URL на структурные части. Используйтеjava.net.URL для этого

2. Правильно закодируйте каждую структурную часть!

3. ИспользуйтеIDN.toASCII(putDomainNameHere) в Punycode закодировать имя хоста!

4 Используйтеjava.net.URI.toASCIIString()т @ до процентного кодирования, кодированного в NFC юникода - (лучше было бы NFKC!). Для получения дополнительной информации см .: Как правильно закодировать этот URL

URL url= new URL("http://example.com/query?q=random word £500 bank $");
URI uri = new URI(url.getProtocol(), url.getUserInfo(), IDN.toASCII(url.getHost()), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
String correctEncodedURL=uri.toASCIIString(); 
System.out.println(correctEncodedURL);

Печать

http://example.com/query?q=random%20word%20%C2%A3500%20bank%20$

Вот несколько примеров, которые также будут работать правильно

{
      "in" : "http://نامه‌ای.com/",
     "out" : "http://xn--mgba3gch31f.com/"
},{
     "in" : "http://www.example.com/‥/foo",
     "out" : "http://www.example.com/%E2%80%A5/foo"
},{
     "in" : "http://search.barnesandnoble.com/booksearch/first book.pdf", 
     "out" : "http://search.barnesandnoble.com/booksearch/first%20book.pdf"
}, {
     "in" : "http://example.com/query?q=random word £500 bank $", 
     "out" : "http://example.com/query?q=random%20word%20%C2%A3500%20bank%20$"
}

URLEncoder. Помимо неправильного имени URLEncoder не имеет ничего общего с URL-адресами), неэффективно (используетStringBuffer вместо Builder и делает несколько других вещей, которые медленны) Это также слишком легко облажаться.

Вместо этого я бы использовалURIBuilder или Spring'sorg.springframework.web.util.UriUtils.encodeQuery или Commons ApacheHttpClient. Причина в том, что вы должны экранировать имя параметров запроса (например, ответ BalusCq) иначе, чем значение параметра.

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

Образец кода

import org.apache.http.client.utils.URIBuilder;

URIBuilder ub = new URIBuilder("http://example.com/query");
ub.addParameter("q", "random word £500 bank \$");
String url = ub.toString();

// Result: http://example.com/query?q=random+word+%C2%A3500+bank+%24

Так как я просто ссылаюсь на другие ответы, я отметил это как вики сообщества. Не стесняйтесь редактировать.

 BalusC03 февр. 2015 г., 19:15
@ Луис:URLEncoder, как говорит его javadoc, намеревался закодировать соответствие параметров строки запросаapplication/x-www-form-urlencoded как описано в спецификации HTML: W3.org / TR / html4 / взаимодействуют / .... Некоторые пользователи действительно путают / злоупотребляют им для кодирования целых URI, как, по-видимому, сделал нынешний ответчик.
 Adam Gent03 февр. 2015 г., 21:12
@ BalusC " Некоторые пользователи действительно путают / злоупотребляют им для кодирования целых URI, как, по-видимому, сделал нынешний ответчик. ". Вы ошиблись. Я никогда не говорил, что я облажался с этим. Я только что видел других, которые сделали это, чьи ошибки я должен исправить. Часть, которую я облажал, состоит в том, что класс URL Java будет принимать неэкранированные скобки, но не класс URI. Есть много способов испортить создание URL, и не все такие блестящие, как вы. Я бы сказал, что большинство пользователей, которые ищут SOR для URLEncoding, вероятно, являются " пользователи действительно путают / злоупотребляют "URI сбежал.
 Adam Gent03 февр. 2015 г., 20:48
@ LuisSep короче URLEncoder для кодирования для отправки формы. Это не для побега. Это не Точный то же самое экранирование, которое вы использовали бы для создания URL-адресов для размещения на вашей веб-странице, но оказалось, что оно достаточно похоже, чтобы люди злоупотребляли им. Единственный раз, когда вы должны использовать URLEncoder, это если вы пишете HTTP-клиент (и даже тогда есть гораздо лучшие варианты для кодирования).
 Luis Sep26 янв. 2015 г., 15:55
Почему это никак не связано с URL-адресами?
 BalusC03 февр. 2015 г., 21:14
Вопрос не об этом, но ваш ответ подразумевает это.
 Emmanuel Touzery16 апр. 2015 г., 13:01
Не уверен, что у них есть проблема. они различают, например, "+" или "% 20" для выхода "" (образуют параметр или путь), которыйURLEncoder нет.
 Paul Taylor02 нояб. 2015 г., 13:18
Это сработало для меня, я просто заменил вызов URLEncoder () для вызова UrlEscapers.urlFragmentEscaper (), и это сработало, не ясно, должен ли я вместо этого использовать UrlEscapers.urlPathSegmentEscaper ().
 mgaert15 июн. 2017 г., 11:50
Ссылка на обновление: UrlEscapers
 2rs2ts29 авг. 2014 г., 00:53
Они страдают от тех же глупых правил ухода, что иURLEncoder.
 Paul Taylor02 нояб. 2015 г., 18:52
На самом деле это не работает для меня, потому что, в отличие от URLEncoder, он не кодирует '+', он оставляет его в покое, сервер декодирует '+' как пробел, тогда как если я использую URLEncoder '+, они преобразуются в% 2B и корректно декодируются обратно в +
Решение Вопроса

URLEncoder должен быть путь. Вам нужно только иметь в виду, чтобы закодироватьтольк имя и / или значение отдельного параметра строки запроса, а не весь URL, наверняка не символ-разделитель параметра строки запроса& ни символ разделитель имя-значение параметра=.

String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");

Обратите внимание, что пробелы в параметрах запроса представлены как+, не%20, который законно действителен.%20 обычно используется для представления пробелов в самом URI (часть перед символом-разделителем строк запроса URI ?), не в строке запроса (часть после?).

Также обратите внимание, что есть дваencode() методы. Один без аргумента charset, а другой с. Один без аргумента charset устарел. Никогда не используйте его и всегда указывайте аргумент charset. Javadoc даже явно рекомендует использовать кодировку UTF-8, как предписано RFC3986 а также W3C.

Все остальные символы небезопасны и сначала преобразуются в один или несколько байтов с использованием некоторой схемы кодирования. Затем каждый байт представлен трехсимвольной строкой «% xy», где xy - шестнадцатеричное представление байта из двух цифр. Рекомендуемая схема кодирования: UTF-8. Однако из соображений совместимости, если кодировка не указана, используется кодировка платформы по умолчанию.

Смотрите также Что каждый веб-разработчик должен знать о кодировке URL
 sharadendu sinha30 июл. 2017 г., 09:15
В URL может быть 2 типа параметров. Строка запроса (сопровождаемая?) И параметр пути (как правило, часть самого URL). Итак, что насчет параметров пути. URLEncoder производит + для пространства даже для параметров пути. Фактически он просто не обрабатывает ничего, кроме строки запроса. Кроме того, это поведение не синхронизировано с серверами узла js. Поэтому для меня этот класс - пустая трата времени, и его нельзя использовать иначе, как для очень специфических / специальных сценариев.
 TmTron03 июл. 2017 г., 16:14
ты должен использовать StandardCharsets.UTF_8 вместо жестко закодированной константы.
 BalusC30 июл. 2017 г., 15:18
@ sharadendusinha: как задокументировано и дано ответ,URLEncoder соответствует параметрам запроса в кодировке URLapplication/x-www-form-urlencoded правила. Параметры пути не вписываются в эту категорию. Вместо этого вам нужен кодировщик URI.
 BalusC15 мар. 2018 г., 10:59
@ WijaySharma: потому что специфичные для URL символы также будут кодироваться. Это следует делать только в том случае, если вы хотите передать весь URL-адрес в качестве параметра запроса другого URL-адреса.
 Jose Duarte28 февр. 2018 г., 18:48
Добавляя к комментарию @TmTron, точнее следует использовать строковую константуStandardCharsets.UTF_8.name()

Сначала нужно создать URI, например:

    String urlStr = "http://www.example.com/CEREC® Materials & Accessories/IPS Empress® CAD.pdf"
    URL url= new URL(urlStr);
    URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());

Затем преобразуйте этот Uri в ASCII-строку:

    urlStr=uri.toASCIIString();

Теперь ваша строка URL полностью закодирована. Сначала мы сделали простое кодирование URL, а затем преобразовали ее в строку ASCII, чтобы убедиться, что в строке не осталось символов вне US-ASCII. Именно так и поступают браузеры.

 M Abdul Sami09 сент. 2015 г., 05:40
@ tibi вы можете просто использовать метод uri.toString () для преобразования его в строку вместо строки Ascii.
 Julian Honma01 сент. 2017 г., 14:44
API, с которым я работал, не приняли+ замена пробелов, но принял% 20, так что это решение работало лучше, чем BalusC, спасибо!
 user1115325 мар. 2015 г., 13:45
Благодарность! Глупо, что ваше решение работает, но встроенноеURL.toURI() нет.
 ZioByte30 апр. 2015 г., 12:23
К сожалению, это, похоже, не работает с "file: ///" (например: "file: /// some / directory / a, содержащий spaces.html"); бомба с MalformedURLException в "новом URL ()"; есть идеи как это исправить?
 M Abdul Sami30 апр. 2015 г., 22:14
Вам нужно сделать что-то вроде этого: String urlStr = " Некоторые / каталог / а файл, содержащий spaces.html "; URL url = новый URL (urlStr); URI uri = новый URI (url.getProtocol (), url.getUserInfo (), url.getHost (), url.getPort (), url.getPath (), url.getQuery (), url.getRef ()); urlStr = uri.toASCIIString (); urlStr.replace ("http: //", "file: ///"); я не проверял его, но я думаю это сработает ....:)

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

String addQueryStringToUrlString(String url, final Map<Object, Object> parameters) throws UnsupportedEncodingException {
    if (parameters == null) {
        return url;
    }

    for (Map.Entry<Object, Object> parameter : parameters.entrySet()) {

        final String encodedKey = URLEncoder.encode(parameter.getKey().toString(), "UTF-8");
        final String encodedValue = URLEncoder.encode(parameter.getValue().toString(), "UTF-8");

        if (!url.contains("?")) {
            url += "?" + encodedKey + "=" + encodedValue;
        } else {
            url += "&" + encodedKey + "=" + encodedValue;
        }
    }

    return url;
}

В Android я бы использовал этот код:

Uri myUI = Uri.parse ("http://example.com/query").buildUpon().appendQueryParameter("q","random word A3500 bank 24").build();

ГдеUri этоandroid.net.Uri

 rmuller10 июл. 2016 г., 10:35
Это не использует стандартный Java API. Поэтому, пожалуйста, укажите используемую библиотеку.

Ваш ответ на вопрос