Допустим, у меня есть URL
http://example.com/query?q=
и у меня есть запрос, введенный пользователем, например:
случайное слово £500 банк $
Я хочу, чтобы результатом был правильно закодированный URL:
http://example.com/query?q=random%20word%20%A3500%20bank%20%24
Каков наилучший способ добиться этого? Я пробовал URLEncoder
и создание объектов URI/URL, но ничего из этого не получилось.
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. Однако, в целях совместимости, если кодировка не указана, то используется кодировка по умолчанию для данной платформы.
Я бы не стал использовать URLEncoder
. Помимо неправильного названия (URLEncoder
не имеет никакого отношения к URL), неэффективности (он использует StringBuffer
вместо Builder и делает пару других медленных вещей), его также слишком легко испортить.
Вместо этого я бы использовал URIBuilder
или Spring's 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());
Затем преобразовать ссылку в строку ASCII:
urlStr=uri.toASCIIString();
Теперь ваша строка url полностью, закодированных сначала мы делали простые кодировки URL-адреса, а затем мы превратили его в ASCII строку, чтобы убедиться, что нет персонажа за пределами ASCII США остаются в строке. Это точно, как браузеры.
Библиотека компонентов в Apache HTTP обеспечивает аккуратный вариант для строительства и кодирование параметров запроса
С HttpComponents 4.X использование - URLEncodedUtils
Для 3 Класса HttpClient.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;
}
Используйте следующие стандартные Java-решение (проходит около 100 тестовых случаев, предусмотренных веб-тестах платформа):
0. Проверить, если URL-адрес уже закодированных. Заменить '+' закодированных пространств '%20' закодированных пространства.
1. Сплит URL в структурные части. Используйте `Ява.чистая.URL-адрес для этого.
2. Кодировать каждую структурную часть правильно!
3. Используйте ИДН.toASCII(putDomainNameHere)
в в Punycode закодировать имя хозяина!
4. Используйте `Ява.чистая.Ури.toASCIIString () на процент-кодирование, поддержка NFC кодировке Юникод - (лучше бы NFKC!). Для более подробной информации смотрите: https://stackoverflow.com/questions/49768599/how-to-encode-properly-this-url/49778055#49778055
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$"
}
В моем случае мне просто нужно, чтобы пройти весь 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");
}
Он использует орг."Апач".общин.lang3.StringUtils
В Android я хотел бы использовать этот код:
Uri myUI = Uri.parse ("http://example.com/query").buildUpon().appendQueryParameter("q","random word A3500 bank 24").build();
Где Ури
это для Андроид.чистая.Ури
Строки encodedUrl1 = UriUtils.encodeQuery(запрос "в кодировке UTF-8 и");//не менять Строки encodedUrl2 = средств кодирования.кодирование(запрос "в кодировке UTF-8 и");//изменено Строки encodedUrl3 = средств кодирования.кодирование(запрос, StandardCharsets.UTF_8.параметр DisplayName());//изменено
Системы.из.код println("Ну и url1 на " + encodedUrl1 + " и\п на" + "и url2=на" + encodedUrl2 + ", У\П на" + "и url3=на" + encodedUrl3);