it-swarm.com.ru

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, но ни один из них не получился совершенно правильным.

639
user1277546

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, а другой с. Один без аргумента charset устарел. Никогда не используйте его и всегда указывайте аргумент charset. javadoc даже явно рекомендует использовать кодировку UTF-8, как предписано RFC3986 и W3C .

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

Смотрите также:

1069
BalusC

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

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

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

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

150
Adam Gent

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

89
M Abdul Sami

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

34
Emmanuel Touzery

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

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

Для HttpClient 3.x используйте - EncodingUtil

6
Sashi

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

Используйте следующее стандартное 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$"
}
4
jschnasse

В моем случае мне просто нужно было передать весь URL и закодировать только значение каждого параметра. Я не нашел общий код для этого (!!), поэтому я создал этот небольшой метод, чтобы сделать работу:

public static String encodeUrl(String url) throws Exception {
    if (url == null || !url.contains("?")) {
        return url;
    }

    List<String> list = new ArrayList<>();
    String rootUrl = url.split("\\?")[0] + "?";
    String paramsUrl = url.replace(rootUrl, "");
    List<String> paramsUrlList = Arrays.asList(paramsUrl.split("&"));
    for (String param : paramsUrlList) {
        if (param.contains("=")) {
            String key = param.split("=")[0];
            String value = param.replace(key + "=", "");
            list.add(key + "=" +  URLEncoder.encode(value, "UTF-8"));
        }
        else {
            list.add(param);
        }
    }

    return rootUrl + StringUtils.join(list, "&");
}

public static String decodeUrl(String url) throws Exception {
    return URLDecoder.decode(url, "UTF-8");
}

Он использует org.Apache.commons.lang3.StringUtils

1
Laurent

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

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

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

0
Sharjeel Lasharie