Meine eigenständige Java-Anwendung erhält vom Benutzer eine URL (die auf eine Datei verweist), und ich muss sie treffen und herunterladen. Das Problem ist, dass ich die HTTP-URL-Adresse nicht richtig codieren kann ...
Beispiel:
URL: http://search.barnesandnoble.com/booksearch/first book.pdf
java.net.URLEncoder.encode(url.toString(), "ISO-8859-1");
gibt mich zurück:
http%3A%2F%2Fsearch.barnesandnoble.com%2Fbooksearch%2Ffirst+book.pdf
Aber was ich will ist
http://search.barnesandnoble.com/booksearch/first%20book.pdf
(Leerzeichen durch% 20 ersetzt)
Ich denke, es URLEncoder
ist nicht dafür ausgelegt, HTTP-URLs zu codieren ... Das JavaDoc sagt "Utility-Klasse für die HTML-Formularcodierung" ... Gibt es eine andere Möglichkeit, dies zu tun?
Antworten:
Die Klasse java.net.URI kann helfen. in der Dokumentation der URL finden Sie
Verwenden Sie einen der Konstruktoren mit mehr als einem Argument, z.
(Der Einzelargument-Konstruktor von URI entgeht NICHT illegalen Zeichen.)
Nur illegale Zeichen werden durch den obigen Code maskiert - es werden KEINE Nicht-ASCII-Zeichen maskiert (siehe Kommentar von fatih).
Die
toASCIIString
Methode kann verwendet werden, um einen String nur mit US-ASCII-Zeichen abzurufen:http://www.google.com/ig/api?weather=São Paulo
Verwenden Sie für eine URL mit einer Abfrage wie die 5-Parameter-Version des Konstruktors:quelle
java.net.URI
: Sie hat perfekt funktioniert (Java 1.6). Ich würde den vollständig qualifizierten Klassennamen erwähnen, wenn es sich nicht um den Standard-Java-Namen handelt und der Link auf die Dokumentation von verweistjava.net.URI
. Und nach dem Kommentar von Sudhakar löste es das Problem, ohne irgendwelche "Commons-Bibliotheken" einzuschließen!Bitte beachten Sie, dass die meisten der oben genannten Antworten falsch sind.
Die
URLEncoder
Klasse ist trotz ihres Namens NICHT das, was hier sein muss. Es ist bedauerlich, dass Sun diese Klasse so nervig benannt hat.URLEncoder
ist zum Übergeben von Daten als Parameter gedacht, nicht zum Codieren der URL selbst.Mit anderen Worten,
"http://search.barnesandnoble.com/booksearch/first book.pdf"
ist die URL. Parameter wären zum Beispiel"http://search.barnesandnoble.com/booksearch/first book.pdf?parameter1=this¶m2=that"
. Die Parameter sind das, wofür Sie sie verwenden würdenURLEncoder
.Die folgenden zwei Beispiele zeigen die Unterschiede zwischen den beiden.
Das Folgende erzeugt die falschen Parameter gemäß dem HTTP-Standard. Beachten Sie, dass das kaufmännische Und (&) und das Pluszeichen (+) falsch codiert sind.
Im Folgenden werden die richtigen Parameter erstellt, wobei die Abfrage ordnungsgemäß codiert wird. Beachten Sie die Leerzeichen, kaufmännischen Und-Zeichen und Pluszeichen.
quelle
query = URLEncoder.encode(key) + "=" + URLEncoder.encode(value)
. Die Dokumente sagen lediglich, dass "jedes Zeichen, das kein legales URI-Zeichen ist, in Anführungszeichen gesetzt wird".Ich werde hier einen Vorschlag hinzufügen, der sich an Android-Benutzer richtet. Sie können dies tun, ohne externe Bibliotheken abrufen zu müssen. Außerdem sind alle in einigen der obigen Antworten vorgeschlagenen Lösungen zum Suchen / Ersetzen von Zeichen gefährlich und sollten vermieden werden.
Probieren Sie es aus:
Sie können sehen, dass in dieser bestimmten URL diese Leerzeichen codiert sein müssen, damit ich sie für eine Anfrage verwenden kann.
Dies nutzt einige Funktionen, die Ihnen in Android-Klassen zur Verfügung stehen. Erstens kann die URL-Klasse eine URL in ihre richtigen Komponenten aufteilen, sodass Sie keine Arbeit zum Suchen / Ersetzen von Zeichenfolgen ausführen müssen. Zweitens nutzt dieser Ansatz die URI-Klassenfunktion, um Komponenten ordnungsgemäß zu maskieren, wenn Sie einen URI über Komponenten anstatt aus einer einzelnen Zeichenfolge erstellen.
Das Schöne an diesem Ansatz ist, dass Sie jede gültige URL-Zeichenfolge verwenden können, ohne dass Sie selbst spezielle Kenntnisse darüber benötigen.
quelle
#
.Eine Lösung, die ich entwickelt habe und die viel stabiler ist als jede andere:
quelle
String utf8Input = new String(Charset.forName("UTF-8").encode(input).array());
(von hier übernommen )Wenn Sie eine URL haben, können Sie url.toString () an diese Methode übergeben. Erste Dekodierung, um eine doppelte Codierung zu vermeiden (z. B. ergibt die Codierung eines Leerzeichens% 20 und die Codierung eines Prozentzeichens% 25, sodass die doppelte Codierung aus einem Leerzeichen% 2520 macht). Verwenden Sie dann den URI wie oben erläutert und fügen Sie alle Teile der URL hinzu (damit Sie die Abfrageparameter nicht löschen).
quelle
Ja, die URL-Codierung wird diese Zeichenfolge so codieren, dass sie in einer URL ordnungsgemäß an ein endgültiges Ziel übergeben wird. Zum Beispiel könnten Sie http://stackoverflow.com?url=http://yyy.com nicht haben . Die Url-Codierung des Parameters würde diesen Parameterwert korrigieren.
Ich habe also zwei Möglichkeiten für Sie:
Haben Sie Zugriff auf den von der Domäne getrennten Pfad? In diesem Fall können Sie den Pfad möglicherweise einfach per Url-Code codieren. Ist dies jedoch nicht der Fall, ist Option 2 möglicherweise für Sie geeignet.
Holen Sie sich commons-httpclient-3.1. Dies hat eine Klasse URIUtil:
System.out.println (URIUtil.encodePath (" http://example.com/x y", "ISO-8859-1"));
Dadurch wird genau das ausgegeben, wonach Sie suchen, da nur der Pfadteil des URI codiert wird.
Zu Ihrer Information, Sie benötigen Commons-Codec und Commons-Logging, damit diese Methode zur Laufzeit funktioniert.
quelle
URIUtil
Lösung verwendetNitpicking: Eine Zeichenfolge, die per Definition ein Leerzeichen enthält, ist keine URI. Sie suchen also nach Code, der das in Abschnitt 2.1 von RFC 3986 definierte URI-Escape implementiert .
quelle
Leider
org.apache.commons.httpclient.util.URIUtil
ist veraltet und diereplacement org.apache.commons.codec.net.URLCodec
Codierung für Formularbeiträge geeignet, nicht in tatsächlichen URLs. Also musste ich meine eigene Funktion schreiben, die eine einzelne Komponente ausführt (nicht geeignet für ganze Abfragezeichenfolgen mit? 'Und &' s)quelle
URLEncoding kann HTTP-URLs problemlos codieren, wie Sie leider festgestellt haben. Die von Ihnen übergebene Zeichenfolge " http://search.barnesandnoble.com/booksearch/first book.pdf" wurde korrekt und vollständig in eine URL-codierte Form codiert. Sie könnten die gesamte lange Zeichenfolge von Gobbledigook übergeben, die Sie als Parameter in einer URL erhalten haben, und sie könnte genau in die Zeichenfolge zurückcodiert werden, die Sie übergeben haben.
Es hört sich so an, als ob Sie etwas anderes tun möchten, als die gesamte URL als Parameter zu übergeben. Soweit ich weiß, versuchen Sie, eine Such-URL zu erstellen, die wie folgt aussieht: " http://search.barnesandnoble.com/booksearch/whateverTheUserPassesIn ". Das einzige, was Sie codieren müssen, ist das Bit "WhateverTheUserPassesIn". Vielleicht müssen Sie also nur Folgendes tun:
Das sollte etwas ziemlich Gültigeres für Sie hervorbringen.
quelle
Wenn jemand seinem Projekt keine Abhängigkeit hinzufügen möchte, können diese Funktionen hilfreich sein.
Wir übergeben hier den 'Pfad'-Teil unserer URL. Sie möchten wahrscheinlich nicht die vollständige URL als Parameter übergeben (Abfragezeichenfolgen benötigen unterschiedliche Escapezeichen usw.).
Und Tests:
quelle
Es gibt immer noch ein Problem, wenn Ihre URL ein verschlüsseltes "/" (% 2F) enthält.
In RFC 3986 - Abschnitt 2.2 heißt es: "Wenn Daten für eine URI-Komponente mit dem Zweck eines reservierten Zeichens als Trennzeichen in Konflikt stehen würden, müssen die widersprüchlichen Daten vor der Bildung des URI prozentual codiert werden." (RFC 3986 - Abschnitt 2.2)
Es gibt jedoch ein Problem mit Tomcat:
Wenn Sie also eine URL mit dem Zeichen% 2F haben, gibt Tomcat Folgendes zurück: "400 Ungültiger URI: noSlash"
Sie können den Bugfix im Tomcat-Startskript umschalten:
quelle
Ich habe die vorherigen Antworten gelesen, um meine eigene Methode zu schreiben, da ich mit der Lösung der vorherigen Antworten nicht richtig arbeiten konnte. Es sieht gut für mich aus. Wenn Sie jedoch eine URL finden, die damit nicht funktioniert, lassen Sie es mich bitte wissen.
quelle
Ich stimme Matt zu. In der Tat habe ich es in Tutorials noch nie gut erklärt gesehen, aber eine Frage ist, wie der URL-Pfad codiert wird, und eine ganz andere ist, wie die Parameter codiert werden, die an die URL angehängt werden (der Abfrageteil hinter dem "? "Symbol). Sie verwenden eine ähnliche Codierung, jedoch nicht dieselbe.
Speziell für die Codierung des Leerzeichens. Der URL-Pfad muss als% 20 codiert sein, während der Abfrageteil% 20 und auch das "+" - Zeichen zulässt. Die beste Idee ist, es selbst mit einem Webbrowser gegen unseren Webserver zu testen.
Für beide Fälle, ich IMMER würde kodieren Komponente für Komponente , nie die ganze Reihe. In der Tat erlaubt URLEncoder dies für den Abfrageteil. Für den Pfadteil können Sie den Klassen-URI verwenden, obwohl in diesem Fall die gesamte Zeichenfolge und nicht eine einzelne Komponente abgefragt wird.
Ich glaube jedenfalls, dass der beste Weg, um diese Probleme zu vermeiden, die Verwendung eines persönlichen, nicht konfliktreichen Designs ist. Wie? Zum Beispiel würde ich niemals Verzeichnisse oder Parameter mit anderen Zeichen als aZ, AZ, 0-9 und _ benennen. Auf diese Weise muss nur der Wert jedes Parameters codiert werden, da er möglicherweise aus einer Benutzereingabe stammt und die verwendeten Zeichen unbekannt sind.
quelle
Vielleicht können Sie UriUtils in org.springframework.web.util ausprobieren
quelle
Sie können auch
GUAVA
Escaper verwenden und verwenden:UrlEscapers.urlFragmentEscaper().escape(relativePath)
quelle
Zusätzlich zur Antwort von Carlos Heuberger: Wenn eine andere als die Standardeinstellung (80) benötigt wird, sollte der Konstruktor 7 param verwendet werden:
quelle
Ich habe den obigen Inhalt genommen und ein wenig geändert. Ich mag zuerst positive Logik, und ich dachte, ein HashSet bietet möglicherweise eine bessere Leistung als einige andere Optionen, wie das Durchsuchen eines Strings. Ich bin mir zwar nicht sicher, ob sich die Autoboxing-Strafe lohnt, aber wenn der Compiler für ASCII-Zeichen optimiert, sind die Kosten für das Boxen niedrig.
quelle
Verwenden Sie die folgende Standard-Java-Lösung (besteht ungefähr 100 der von Web Plattform Tests bereitgestellten Testfälle ):
0. Testen Sie, ob die URL bereits codiert ist .
1. Teilen Sie die URL in Strukturteile auf. Verwenden
java.net.URL
Sie dafür.2. Codieren Sie jedes Bauteil richtig!
3. Verwenden Sie Punycode, um den Hostnamen
IDN.toASCII(putDomainNameHere)
zu codieren!4. Verwenden Sie
java.net.URI.toASCIIString()
, um NFC-codierten Unicode in Prozent zu codieren - (besser wäre NFKC!).Weitere Informationen finden Sie hier: https://stackoverflow.com/a/49796882/1485527
quelle
Ich habe ein neues Projekt erstellt, um beim Erstellen von HTTP-URLs zu helfen. Die Bibliothek codiert Pfadsegmente und Abfrageparameter automatisch per URL.
Sie können die Quelle anzeigen und eine Binärdatei unter https://github.com/Widen/urlbuilder herunterladen
Die Beispiel-URL in dieser Frage:
produziert
http://search.barnesandnoble.com/booksearch/first%20book.pdf
quelle
Ich hatte das gleiche Problem. Gelöst durch Unsing:
Es codiert die Zeichenfolge, überspringt jedoch ":" und "/".
quelle
ich benutze das
Fügen Sie diese Abhängigkeit hinzu
quelle
Ich entwickle eine Bibliothek, die diesem Zweck dient: Galimaten . Es analysiert URLs genauso wie Webbrowser. Das heißt, wenn eine URL in einem Browser funktioniert, wird sie von Galimaten korrekt analysiert .
In diesem Fall:
Wird Ihnen geben :
http://search.barnesandnoble.com/booksearch/first%20book.pdf
. Natürlich ist dies der einfachste Fall, aber es wird mit allem funktionieren, weit darüber hinausjava.net.URI
.Sie können es unter folgender Adresse überprüfen: https://github.com/smola/galimatias
quelle
Sie können eine solche Funktion verwenden. Vervollständigen Sie es und passen Sie es an Ihre Bedürfnisse an:
Anwendungsbeispiel:
Das Ergebnis ist: http://www.growup.com/folder/int%C3%A9rieur-%C3%A0_vendre?o=4
quelle
String url = "" http://search.barnesandnoble.com/booksearch/ ;
Dies wird wahrscheinlich konstant sein und nur der Dateiname ändert sich dyamisch, also erhalte den Dateinamen
String Dateiname; // den Dateinamen abrufen
String urlEnc = url + fileName.replace ("", "% 20");
quelle
Wie wäre es mit:
public String UrlEncode (String in_) {
}}
quelle