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

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

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

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

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

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

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

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

9 ответов


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

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

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

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

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

Читайте также:


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

вместо этого я бы использовал URIBuilder или весной 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

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


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


гуава 15 теперь добавил набор простых эскейперов URL.


Apache Http Components library предоставляет аккуратный вариант для построения и кодирования запросов params -

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

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


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

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

2. кодировать каждую структурную часть правильно!

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

4. использовать java.net.URI.toASCIIString() в процентах-кодирование, кодировка NFC unicode - (лучше было бы 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$

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

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

здесь Uri это android.net.Uri


  1. используйте это: URLEncoder.encode (query, StandardCharsets.UTF_8.значение DisplayName()); или это: URLEncoder.encode (query, "UTF-8");
  2. вы можете использовать код ниже.

    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);