Кодировка URL-адресов Java для параметров строки запроса

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

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

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

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

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

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

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

Ответ 1

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

String q = "random word £500 bank $";
String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");

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

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

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

См. также:

Ответ 2

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

Вместо этого я бы использовал URIBuilder или Spring org.springframework.web.util.UriUtils.encodeQuery или Commons Apache HttpClient. Причина в том, что вам нужно избегать имени параметров запроса (то есть ответ BalusC q) иначе, чем значение параметра.

Единственный недостаток вышеизложенного (что я обнаружил мучительно) заключается в том, что 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

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

Ответ 3

Вам нужно сначала создать 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 String, чтобы убедиться, что в строке нет символа вне US-ASCII. Именно так работают браузеры.

Ответ 5

Библиотека Apache Http Components предоставляет опрятную опцию для создания и кодирования параметров запроса -

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

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

Ответ 6

Здесь вы можете использовать в своем коде для преобразования строки 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;
}

Ответ 7

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

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

Где Uri является android.net.Uri

Ответ 8

Используйте следующее стандартное решение Java (проходит около 100 тестовых случаев, предоставляемых Web Plattform Tests):

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$"
}

Ответ 9

  • Используйте это: 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);
    

Ответ 10

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

var Url="https://http://localhost:50826/#/Post-Detail/12"

var EncodedUri=encodeURIComponent(Url);