it-swarm.com.de

Java URL-Codierung von Abfragezeichenfolgenparametern

Angenommen, ich habe eine URL

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

und ich habe eine vom Benutzer eingegebene Anfrage wie:

zufälliges Wort £ 500 Bank $

Ich möchte, dass das Ergebnis eine richtig codierte URL ist:

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

Was ist der beste Weg, um dies zu erreichen? Ich habe URLEncoder ausprobiert und URI/URL-Objekte erstellt, aber keines davon ist richtig.

660
user1277546

URLEncoder sollte der richtige Weg sein. Sie müssen nur berücksichtigen, dass nur der Name und/oder der Wert des einzelnen Abfragezeichenfolgenparameters codiert werden muss, nicht die gesamte URL, mit Sicherheit nicht das Trennzeichen für Abfragezeichenfolgenparameter & oder das Parametername-Wert-Trennzeichen =.

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

Beachten Sie, dass Leerzeichen in Abfrageparametern durch + und nicht durch %20 dargestellt werden, was legitimerweise gültig ist. Der %20 wird normalerweise verwendet, um Leerzeichen in der URI selbst darzustellen (der Teil vor dem Trennzeichen für die URI-Abfragezeichenfolge ?), nicht in der Abfragezeichenfolge (der Teil nach ?).

Beachten Sie auch, dass es zwei encode() Methoden gibt. Eines ohne Zeichensatzargument und eines mit. Das Argument ohne Zeichensatz ist veraltet. Verwenden Sie es niemals und geben Sie immer das charset-Argument an. In javadoc wird sogar ausdrücklich empfohlen, die UTF-8-Codierung zu verwenden, wie von RFC3986 und W3C vorgeschrieben.

Alle anderen Zeichen sind unsicher und werden zuerst mit einem Kodierungsschema in ein oder mehrere Bytes konvertiert. Dann wird jedes Byte durch die 3-stellige Zeichenfolge "% xy" dargestellt, wobei xy die zweistellige hexadezimale Darstellung des Bytes ist. Das empfohlene Codierungsschema ist UTF-8 . Wenn jedoch aus Kompatibilitätsgründen keine Codierung angegeben wird, wird die Standardcodierung der Plattform verwendet.

Siehe auch:

1092
BalusC

Ich würde URLEncoder nicht verwenden. Abgesehen davon, dass der falsche Name (URLEncoder hat nichts mit URLs zu tun), ist er ineffizient (er verwendet StringBuffer anstelle von Builder und erledigt einige andere langsame Dinge).

Stattdessen würde ich URIBuilder oder Spring's org.springframework.web.util.UriUtils.encodeQuery oder Commons Apache HttpClient verwenden. Der Grund dafür ist, dass Sie den Abfrageparameternamen (dh BalusCs Antwort q) anders als den Parameterwert umgehen müssen.

Der einzige Nachteil des oben genannten (was ich schmerzhaft herausgefunden habe) ist, dass RLs sind keine echte Teilmenge von URIs .

Beispielcode:

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

Da ich nur auf andere Antworten verweise, habe ich dies als Community-Wiki markiert. Fühlen Sie sich frei zu bearbeiten.

157
Adam Gent

Sie müssen zuerst eine URI wie folgt erstellen:

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

Konvertieren Sie dann diesen Uri in den ASCII String:

    urlStr=uri.toASCIIString();

Jetzt ist Ihre URL-Zeichenfolge vollständig codiert. Zuerst haben wir eine einfache URL-Codierung durchgeführt und diese dann in die Zeichenfolge ASCII konvertiert, um sicherzustellen, dass keine Zeichen außerhalb von US-ASCII in der Zeichenfolge verbleiben. Genau so machen es Browser.

92
M Abdul Sami

Guava 15 hat jetzt eine Reihe einfacher URL-Escaper hinzugefügt.

34

Die Apache Http Components-Bibliothek bietet eine praktische Option zum Erstellen und Codieren von Abfrageparametern.

Verwenden Sie bei HttpComponents 4.x - RLEncodedUtils

Verwenden Sie für HttpClient 3.x - EncodingUtil

6
Sashi

Hier ist eine Methode, die Sie in Ihrem Code verwenden können, um eine URL-Zeichenfolge und eine Zuordnung von Parametern in eine gültige codierte URL-Zeichenfolge zu konvertieren, die die Abfrageparameter enthält.

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

Verwenden Sie die folgende Standardlösung Java (übergibt ungefähr 100 der Testfälle, die von Web Plattform Tests bereitgestellt werden):

0. Prüfen Sie, ob die URL bereits verschlüsselt ist . Ersetzen Sie '+' codierte Leerzeichen durch '% 20' codierte Leerzeichen.

1. URL in Strukturteile aufteilen. Verwenden Sie dafür Java.net.URL.

2. Codieren Sie jedes Bauteil richtig!

3. Verwenden Sie IDN.toASCII(putDomainNameHere), um Punycode den Hostnamen zu codieren!

4. Verwenden Sie Java.net.URI.toASCIIString() zum prozentualen Codieren, NFC codierten Unicode besser wäre NFKC!). Weitere Informationen finden Sie unter: --- (So codieren Sie diese URL richtig

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

Druckt

http://example.com/query?q=random%20Word%20%C2%A3500%20bank%20$

Hier sind einige Beispiele, die auch richtig funktionieren

{
      "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

In meinem Fall musste ich nur die gesamte URL übergeben und nur den Wert der einzelnen Parameter codieren. Ich habe keinen gemeinsamen Code gefunden, um das zu tun (!!), also habe ich diese kleine Methode erstellt, um die Arbeit zu erledigen:

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

Es verwendet org.Apache.commons.lang3.StringUtils

1
Laurent

In Android würde ich diesen Code verwenden:

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

Wobei Uri ein Android.net.Uri ist

0