391 Stimmen

HTTP-URL-Adresskodierung in Java

Meine Java-Standalone-Anwendung erhält vom Benutzer eine URL (die auf eine Datei verweist), und ich muss sie anklicken und herunterladen. Das Problem, das ich konfrontiert bin, ist, dass ich nicht in der Lage bin, die HTTP-URL-Adresse richtig zu kodieren...

Ejemplo:

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 ersetzt durch %20)

Ich denke URLEncoder ist nicht dafür ausgelegt, HTTP-URLs zu kodieren... In der JavaDoc heißt es "Utility class for HTML form encoding"... Gibt es eine andere Möglichkeit, dies zu tun?

8voto

Emilien Brigand Punkte 8323

Ich habe die vorherigen Antworten gelesen, um meine eigene Methode zu schreiben, weil ich mit der Lösung der vorherigen Antworten nicht richtig arbeiten konnte. Für mich sieht es gut aus, aber wenn Sie eine URL finden, die nicht mit dieser funktioniert, lassen Sie es mich bitte wissen.

public static URL convertToURLEscapingIllegalCharacters(String toEscape) throws MalformedURLException, URISyntaxException {
            URL url = new URL(toEscape);
            URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
            //if a % is included in the toEscape string, it will be re-encoded to %25 and we don't want re-encoding, just encoding
            return new URL(uri.toString().replace("%25", "%"));
}

5voto

micahli123 Punkte 430

Vielleicht können Sie versuchen UriUtils in org.springframework.web.util

UriUtils.encodeUri(input, "UTF-8")

5voto

To Kra Punkte 2979

Sie können auch Folgendes verwenden GUAVA und Pfadbegleiter: UrlEscapers.urlFragmentEscaper().escape(relativePath)

4voto

negora Punkte 151

Ich stimme mit Matt überein. In der Tat habe ich nie gesehen, dass es in Tutorien gut erklärt wird, aber eine Sache ist, wie man den URL-Pfad kodiert, und eine ganz andere, wie man die Parameter kodiert, die an die URL angehängt werden (der Abfrageteil, hinter dem "?" Symbol). Sie verwenden eine ähnliche Kodierung, aber nicht dieselbe.

Speziell für die Kodierung des Leerzeichens. Für den URL-Pfad muss es als %20 kodiert sein, während der Abfrageteil %20 und auch das "+"-Zeichen zulässt. Am besten ist es, wenn Sie es selbst mit einem Webbrowser auf unserem Webserver testen.

Für beide Fälle gilt: I IMMER würde verschlüsseln KOMPONENTE FÜR KOMPONENTE nie die gesamte Zeichenfolge. In der Tat erlaubt URLEncoder dies für den Abfrageteil. Für den Pfadteil können Sie die Klasse URI verwenden, obwohl in diesem Fall die gesamte Zeichenkette abgefragt wird, nicht eine einzelne Komponente.

Wie auch immer, ich glaube, dass Der beste Weg, diese Probleme zu vermeiden, ist die Verwendung eines persönlichen, konfliktfreien Designs. Wie? Ich würde zum Beispiel niemals Verzeichnisse oder Parameter mit anderen Zeichen als a-Z, A-Z, 0-9 und _ benennen. Auf diese Weise muss nur der Wert jedes Parameters kodiert werden, da er von einer Benutzereingabe stammen kann und die verwendeten Zeichen unbekannt sind.

3voto

ChrisG65 Punkte 61

Ich habe den obigen Inhalt genommen und ihn ein wenig verändert. Ich mag positive Logik zuerst, und ich dachte, ein HashSet könnte eine bessere Leistung als einige andere Optionen, wie die Suche durch einen String. Obwohl, ich bin nicht sicher, ob die autoboxing Strafe ist es wert, aber wenn der Compiler für ASCII-Zeichen optimiert, dann die Kosten der Boxing wird niedrig sein.

/***
 * Replaces any character not specifically unreserved to an equivalent 
 * percent sequence.
 * @param s
 * @return
 */
public static String encodeURIcomponent(String s)
{
    StringBuilder o = new StringBuilder();
    for (char ch : s.toCharArray()) {
        if (isSafe(ch)) {
            o.append(ch);
        }
        else {
            o.append('%');
            o.append(toHex(ch / 16));
            o.append(toHex(ch % 16));
        }
    }
    return o.toString();
}

private static char toHex(int ch)
{
    return (char)(ch < 10 ? '0' + ch : 'A' + ch - 10);
}

// https://tools.ietf.org/html/rfc3986#section-2.3
public static final HashSet<Character> UnreservedChars = new HashSet<Character>(Arrays.asList(
        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
        '0','1','2','3','4','5','6','7','8','9',
        '-','_','.','~'));
public static boolean isSafe(char ch)
{
    return UnreservedChars.contains(ch);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X