Kodowanie adresów URL w języku Java parametrów ciągów zapytań

Say I have a URL

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

I mam zapytanie wprowadzone przez użytkownika takie jak:

Losowe słowo £ 500 bank $

Chcę, aby wynik był poprawnie zakodowanym adresem URL:

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

Jaki jest najlepszy sposób, aby to osiągnąć? Próbowałem URLEncoder i tworzyć obiekty URI / URL, ale żaden z nich nie wychodzi całkiem dobrze.

Author: Abdull, 2012-05-28

9 answers

URLEncoder to powinna być droga. Musisz tylko pamiętać, aby zakodować tylko nazwę i/lub wartość pojedynczego parametru ciągu zapytania, a nie cały adres URL, na pewno nie znak separatora parametru ciągu zapytania & ani znak separatora nazwa-wartość parametru =.

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

Zauważ, że spacje w parametrach zapytania są reprezentowane przez +, a nie %20, co jest prawnie ważne. %20 jest zwykle używany do reprezentowania spacji w URI sama (część przed Uri-query string separator znaków ?), a nie w query string (część po ?).

Zauważ również, że istnieją dwie metody encode(). Jeden bez argumentu charset, a drugi z. Ten bez argumentu charset jest przestarzały. Nigdy go nie używaj i zawsze podaj argument charset. javadoc zaleca nawet używanie kodowania UTF-8, zgodnie z nakazem RFC3986 i W3C .

Wszystkie inne znaki są niebezpieczne i są najpierw konwertowane na jeden lub więcej bajtów przy użyciu jakiegoś schematu kodowania. Następnie każdy bajt jest reprezentowany przez 3-znakowy łańcuch "%xy", gdzie xy jest dwucyfrową szesnastkową reprezentacją bajtu. zalecanym schematem kodowania jest UTF-8 . Jednak ze względu na kompatybilność, jeśli kodowanie nie jest określone, używane jest domyślne kodowanie platformy.

Zobacz też:

 959
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-14 07:59:00

Nie użyłbym URLEncoder. Poza tym, że jest niepoprawnie nazwany (URLEncoder nie ma nic wspólnego z adresami URL), nieefektywny (używa StringBuffer zamiast Buildera i robi kilka innych rzeczy, które są powolne)jest również zbyt łatwy do spieprzenia.

Zamiast tego użyłbym URIBuilder lub Spring ' s org.springframework.web.util.UriUtils.encodeQuery lub Commons Apache HttpClient. Powodem jest to, że musisz uciec nazwę parametrów zapytania (tj. odpowiedź BalusC q) inaczej niż wartość parametru.

Jedynym minusem do powyższe (że dowiedziałem się boleśnie) jest to, że URL nie są prawdziwym podzbiorem URI .

Przykładowy kod:

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

ponieważ tylko linkuję do innych odpowiedzi, zaznaczyłem to jako wiki społeczności. Zapraszam do edycji.

 140
Author: Adam Gent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-17 11:39:34

Musisz najpierw utworzyć URI w stylu:

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

Następnie przekonwertuj ten Uri na ciąg ASCII:

    urlStr=uri.toASCIIString();

Teraz twój ciąg url jest całkowicie zakodowany najpierw zrobiliśmy proste kodowanie url, a następnie przekonwertowaliśmy go do ASCII ciąg, aby upewnić się, że żaden znak poza nami-ASCII pozostały w ciągu. Tak właśnie robią przeglądarki.

 86
Author: M Abdul Sami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-09 00:52:06
 29
Author: Emmanuel Touzery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-15 20:34:41

Biblioteka komponentów Http Apache dostarcza ładną opcję do budowania i kodowania query params-

Z HttpComponents 4.x użycie - URLEncodedUtils

Dla HttpClient 3.x użycie - EncodingUtil

 6
Author: Sashi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-06 20:49:47

Oto metoda, której możesz użyć w kodzie, aby przekonwertować ciąg url i mapę parametrów na poprawny zakodowany ciąg url zawierający parametry zapytania.

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
Author: Pellet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-02 00:34:30

1. podziel adres URL na części strukturalne. Użyj java.net.URL do tego.

2. Zakoduj każdą część strukturalną poprawnie!

3. Użyj IDN.toASCII(putDomainNameHere) Aby Punycode zakodować nazwę hosta!

4. Użyj java.net.URI.toASCIIString() do kodowania procentowego, kodowania NFC Unicode - (lepiej byłoby NFKC!). Aby uzyskać więcej informacji zobacz: jak poprawnie zakodować ten adres 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);

Druki

http://example.com/query?q=random%20word%20%C2%A3500%20bank%20$
 1
Author: jschnasse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 15:06:28

W Androidzie użyłbym tego kodu:

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

Gdzie Uri jest android.net.Uri

 1
Author: Sharjeel Lasharie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-21 20:29:54
  1. Użyj tego: Urlencodera.encode( query, StandardCharsets.UTF_8.displayName()); albo to:URLEncoder.encode(query, "UTF-8");
  2. Możesz użyć kodu follwing.

    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);
    
 -2
Author: Xuelian Han,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-21 07:59:58