Codieren von URL-Abfrageparametern in Java

107

Wie codiert man Abfrageparameter für eine URL in Java? Ich weiß, das scheint eine offensichtliche und bereits gestellte Frage zu sein.

Es gibt zwei Feinheiten, bei denen ich mir nicht sicher bin:

  1. Sollten Leerzeichen in der URL als "+" oder als "% 20" codiert werden? Wenn ich in Chrome "http://google.com/foo=?bar me" eingebe, ändert Chrome es so, dass es mit% 20 codiert wird
  2. Ist es notwendig / richtig, Doppelpunkte ":" als% 3B zu codieren? Chrome nicht.

Anmerkungen:

  • java.net.URLEncoder.encodescheint nicht zu funktionieren, es scheint zu sein, dass Codierungsdaten vom Formular gesendet werden. Beispielsweise wird der Speicherplatz als +anstelle von %20und der Doppelpunkt codiert, der nicht erforderlich ist.
  • java.net.URI codiert keine Abfrageparameter
Alex Black
quelle
Diese Frage sieht nützlich aus: stackoverflow.com/questions/444112/…
Alex Black
2
Die Struktur des Abfrageteils ist serverabhängig, obwohl die meisten application/x-www-form-urlencodedSchlüssel / Wert-Paare erwarten . Weitere Informationen finden
McDowell

Antworten:

127

java.net.URLEncoder.encode(String s, String encoding)kann auch helfen. Es folgt der HTML-Formularcodierung application/x-www-form-urlencoded.

URLEncoder.encode(query, "UTF-8");

Auf der anderen Seite codiert die Prozentcodierung (auch als URL-Codierung bezeichnet ) Speicherplatz mit %20. :Doppelpunkt ist ein reserviertes Zeichen, bleibt also nach der Codierung ein Doppelpunkt.

Buhake Sindi
quelle
3
Ich erwähnte, dass ich nicht dachte, dass dies eine URL-Codierung ist, sondern dass es Daten codiert, die über ein Formular gesendet werden sollen. Bemerkungen?
Alex Black
Das liegt daran , URLEncoderzu angepasst wird application/x-www-form-urlencodedMIME - Format (die eine gültige HTML - Formular - Codierung). Ich gehe davon aus, dass Sie nicht danach suchen.
Buhake Sindi
6
Am Ende habe ich URLEncoder.encode verwendet und "+" durch "% 20" ersetzt
Alex Black
2
Es codiert Schrägstriche in "% 2F". Sollte es die URL-Schrägstriche nicht so lassen, wie sie sind?
Golimar
6
@ Golimar Nein, sollte es nicht. Sie sollten nur den Parameterwert und nicht die gesamte URL angeben. Betrachten Sie ein Beispiel http://example.com/?url=http://example.com/?q=c&sort=name. Sollte es codieren &sort=nameoder nicht? Es gibt keine Möglichkeit, den Wert von der URL zu unterscheiden. Das ist genau der Grund, warum Sie überhaupt eine Wertcodierung benötigen.
Pijusn
15

BEARBEITEN: URIUtilist in neueren Versionen nicht mehr verfügbar, bessere Antwort unter Java - Codierungs-URL oder von Herrn Sindi in diesem Thread.


URIUtilvon Apache httpclient ist wirklich nützlich, obwohl es einige Alternativen gibt

URIUtil.encodeQuery(url);

Beispielsweise wird der Speicherplatz als "+" anstelle von "% 20" codiert.

Beide sind im richtigen Kontext vollkommen gültig . Wenn Sie es wirklich vorziehen, können Sie eine Zeichenfolge ersetzen.

Johan Sjöberg
quelle
Ich müsste zustimmen. Verwenden Sie HttpClient, Sie werden viel glücklicher sein.
DaShaun
Das sieht vielversprechend aus, hast du zufällig einen Link? Ich google, finde aber viele.
Alex Black
1
Diese Methode scheint in HttpClient 4.1 nicht vorhanden zu sein. hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Alex Black
@ Alex, hmm das ist nervig, ich habe diese Routine immer mit guten Ergebnissen verwendet. Eine Idee ist, den Quellcode aus der Version 3 zu holen, da sie ihn jetzt offensichtlich nicht mehr pflegen wollten.
Johan Sjöberg
1
URIUtil.encodeWithinQueryist das, was Sie verwenden würden, um einen einzelnen Abfrageparameter zu codieren, was die ursprüngliche Frage zu sein schien.
Jesse Glick
13

Leider erzeugt URLEncoder.encode () keine gültige Prozentcodierung (wie in RFC 3986 angegeben ).

URLEncoder.encode () codiert alles einwandfrei, außer dass das Leerzeichen mit "+" codiert ist. Alle Java-URI-Encoder, die ich finden konnte, legen nur öffentliche Methoden zum Codieren der Abfrage, des Fragments, der Pfadteile usw. offen - aber nicht die "rohe" Codierung. Dies ist unglücklich, da Fragment und Abfrage Speicherplatz in + codieren dürfen, sodass wir sie nicht verwenden möchten. Der Pfad wird ordnungsgemäß codiert, aber zuerst "normalisiert", sodass wir ihn auch nicht für die "generische" Codierung verwenden können.

Beste Lösung, die ich finden konnte:

return URLEncoder.encode(raw, "UTF-8").replaceAll("\\+", "%20");

Wenn replaceAll()es Ihnen zu langsam ist, besteht die Alternative wohl darin, Ihren eigenen Encoder zu rollen ...

EDIT: Ich hatte diesen Code zuerst hier, der "?", "&", "=" Nicht richtig codiert:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);
Kosta
quelle
+ist eine vollkommen gültige Kodierung eines Raumes.
Lawrence Dol
@ LawrenceDol es ist wahr, aber manchmal +kann es falsch interpretiert werden - werfen Sie einen Blick auf C # blogs.msdn.microsoft.com/yangxind/2006/11/08/…
Lu55
Dies. Ich habe verschiedene Alternativen mit der encodeURIComponentAusgabe von Javascript verglichen , und dies war die einzige exakte Übereinstimmung mit denen, die ich ausprobiert habe (Abfragen mit Leerzeichen, türkischen und deutschen Sonderzeichen).
Utku Özdemir
8

Es ist nicht erforderlich, einen Doppelpunkt in der Abfrage als% 3B zu codieren, obwohl dies nicht unzulässig ist.

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Es scheint auch, dass nur prozentual codierte Leerzeichen gültig sind, da ich bezweifle, dass das Leerzeichen ein ALPHA oder ein DIGIT ist

Weitere Informationen finden Sie in der URI-Spezifikation .

Edwin Buck
quelle
Dies kann jedoch die Bedeutung des URI ändern, da die Interpretation der Abfragezeichenfolge dem Server überlassen bleibt. Wenn Sie eine application/x-www-form-urlencodedAbfragezeichenfolge erstellen, ist beides in Ordnung. Wenn Sie eine URL reparieren, die der Benutzer eingegeben / eingefügt hat, :sollten Sie diese in Ruhe lassen.
tc.
@tc. Sie haben Recht, wenn der Doppelpunkt als allgemeines Trennzeichen verwendet wird (Seite 12 des RFC). Wenn es jedoch nicht als allgemeines Trennzeichen verwendet wird, sollten beide Codierungen identisch aufgelöst werden.
Edwin Buck
Sie müssen auch vorsichtig sein, da URLs nicht wirklich eine Teilmenge der URI sind: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent
5

Der eingebaute Java URLEncoder macht das, was er soll, und Sie sollten ihn verwenden.

Ein „+“ oder „% 20“ ist beide gültiger Ersatz für ein Leerzeichen in einer URL. Entweder wird man arbeiten.

Ein ":" sollte codiert werden, da es sich um ein Trennzeichen handelt. dh http: // foo oder ftp: // bar . Die Tatsache, dass ein bestimmter Browser damit umgehen kann, wenn er nicht codiert ist, macht es nicht korrekt. Sie sollten sie codieren.

Verwenden Sie als bewährte Methode unbedingt die Methode, die einen Zeichenkodierungsparameter verwendet. Dort wird in der Regel UTF-8 verwendet, das Sie jedoch explizit angeben sollten.

URLEncoder.encode(yourUrl, "UTF-8");
rfeak
quelle
5
+ist nur eine Darstellung des Raumes in application/x-www-form-urlencoded; Es ist nicht garantiert, dass es funktioniert, auch wenn es auf HTTP beschränkt ist. Ebenso :ist in einer Abfragezeichenfolge gültig und sollte nicht in konvertiert werden %3B; Ein Server kann sie unterschiedlich interpretieren.
tc.
1
Diese Methode kodieren auch ganze URL Schrägstriche und andere Zeichen , die Teil sind zB http://zu http%3A%2F%2Fdem ist nicht korrekt
Um Kra
2
@ ToKra Sie sollen das http://Teil nicht codieren . Die Methode ist für Abfrageparameter und codierte Formulardaten. Wenn Sie jedoch die URL einer anderen Website als Abfrageparameter übergeben möchten, möchten Sie sie dann codieren, um eine Verwechslung des URL-Parsers zu vermeiden.
Beldaz
@tc Beim Lesen von w3.org/TR/html4/interact/forms.html#h-17.13.3.3 werden alle GET-Formulardaten als application/x-www-form-urlencodedInhaltstyp codiert . Bedeutet das nicht, dass es für HTTP funktionieren muss?
Beldaz
0

Wenn Sie nur Platzprobleme in der URL haben. Ich habe unten Code verwendet und es funktioniert gut

String url;
URL myUrl = new URL(url.replace(" ","%20"));

Beispiel: URL ist

www.xyz.com?para=hello Sir

dann ist die Ausgabe von muUrl

www.xyz.com?para=hello%20sir

Jignesh Patel
quelle
0
String param="2019-07-18 19:29:37";
param="%27"+param.trim().replace(" ", "%20")+"%27";

Ich habe festgestellt, dass im Fall von Datetime (Timestamp) URLEncoder.encode(param,"UTF-8")nicht funktioniert.

ICL Sales EXIMON
quelle