390 Stimmen

Swift - URL codieren

Wenn ich einen String so kodiere:

var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

werden die Schrägstriche / nicht maskiert.

Ich habe gesucht und diesen Objective-C-Code gefunden:

NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                        NULL,
                        (CFStringRef)unencodedString,
                        NULL,
                        (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                        kCFStringEncodingUTF8 );

Gibt es einen einfacheren Weg, eine URL zu codieren und wenn nicht, wie schreibe ich das in Swift?

32voto

AJP Punkte 23971

Swift 4 & 5 (Dank an @sumizome für den Vorschlag. Dank an @FD_ und @derickito für das Testen)

var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed
allowedQueryParamAndKey.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

Swift 3

let allowedQueryParamAndKey =  NSCharacterSet.urlQueryAllowed.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

Swift 2.2 (Aus Zaph's übernommen und für die URL-Abfragezeichen und Parameterwerte korrigiert)

var allowedQueryParamAndKey =  NSCharacterSet(charactersInString: ";/?:@&=+$, ").invertedSet
paramOrKey.stringByAddingPercentEncodingWithAllowedCharacters(allowedQueryParamAndKey)

Beispiel:

let paramOrKey = "https://some.website.com/path/to/page.srf?a=1&b=2#top"
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)
// ergibt:
"https%3A%2F%2Fsome.website.com%2Fpath%2Fto%2Fpage.srf%3Fa%3D1%26b%3D2%23top"

Dies ist eine kürzere Version von Bryans Antwort. Ich vermute, dass urlQueryAllowed die Steuerzeichen durchlässt, was in Ordnung ist, es sei denn, sie bilden einen Teil des Schlüssels oder Werts in Ihrer Abfragezeichenfolge, an welchem Punkt sie maskiert werden müssen.

17voto

Alessandro Ornano Punkte 33106

Swift 4:

Es hängt von den Kodierungsregeln ab, die von Ihrem Server befolgt werden.

Apple bietet diese Klassenmethode an, aber sie gibt nicht an, welches Art von RCF-Protokoll sie befolgt.

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!

Mit diesem nützlichen Tool sollten Sie die Kodierung dieser Zeichen für Ihre Parameter garantieren:

  • $ (Dollarzeichen) wird zu %24
  • & (Ampersand) wird zu %26
  • + (Plus) wird zu %2B
  • , (Komma) wird zu %2C
  • : (Doppelpunkt) wird zu %3A
  • ; (Semikolon) wird zu %3B
  • \= (Gleichheitszeichen) wird zu %3D
  • ? (Fragezeichen) wird zu %3F
  • @ (Klammeraffe) wird zu %40

Andere Worte, wenn es um die URL-Kodierung geht, sollten Sie das RFC 1738-Protokoll befolgen.

Und Swift kümmert sich nicht um die Kodierung des + Zeichens zum Beispiel, aber es funktioniert gut mit diesen drei @ : ? Zeichen.

Also, um jeden Parameter korrekt zu kodieren, reicht die Option .urlHostAllowed nicht aus, Sie sollten auch die Sonderzeichen wie zum Beispiel hinzufügen:

encodedParameter = parameter.replacingOccurrences(of: "+", with: "%2B")

Hoffentlich hilft dies jemandem, der verrückt wird, um diese Informationen zu suchen.

15voto

Bryan Chen Punkte 44646

Alles ist gleich

var str = CFURLCreateStringByAddingPercentEscapes(
    nil,
    "test/test",
    nil,
    "!*'();:@&=+$,/?%#[]",
    CFStringBuiltInEncodings.UTF8.rawValue
)

// test%2Ftest

12voto

andrewjazbec Punkte 869

Swift 4.2

Eine schnelle Einzeillösung. Ersetzen Sie originalString durch den String, den Sie codieren möchten.

var encodedString = originalString.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]{} ").inverted)

Online Playground Demo

6voto

CartoonChess Punkte 573

Dies funktioniert für mich in Swift 5. Das Anwendungsbeispiel besteht darin, eine URL aus der Zwischenablage oder ähnlichem zu übernehmen, die bereits maskierte Zeichen enthalten kann, aber auch Unicode-Zeichen, die dazu führen könnten, dass URLComponents oder URL(string:) fehlschlagen.

Zunächst wird ein Zeichensatz erstellt, der alle für URLs zulässigen Zeichen enthält:

extension CharacterSet {

    /// Zeichen, die mindestens in einem Teil einer URL gültig sind.
    ///
    /// Diese Zeichen sind nicht in ALLEN Teilen einer URL erlaubt; jeder Teil hat unterschiedliche Anforderungen. Dieser Satz ist hilfreich, um nach Unicode-Zeichen zu suchen, die vor der Durchführung eines Gültigkeitschecks für einzelne URL-Komponenten Prozent-codiert werden müssen.
    static var urlAllowedCharacters: CharacterSet {
        // Beginne mit Hashtag, der in keinem Satz enthalten ist
        var characters = CharacterSet(charactersIn: "#")
        // Alle für URLs zulässigen Zeichen
        characters.formUnion(.urlUserAllowed)
        characters.formUnion(.urlPasswordAllowed)
        characters.formUnion(.urlHostAllowed)
        characters.formUnion(.urlPathAllowed)
        characters.formUnion(.urlQueryAllowed)
        characters.formUnion(.urlFragmentAllowed)

        return characters
    }
}

Anschließend wird String erweitert um eine Methode zum Codieren von URLs:

extension String {

    /// Wandelt eine Zeichenfolge in eine Prozent-codierte URL um, einschließlich Unicode-Zeichen.
    ///
    /// - Gibt zurück: Eine codierte URL, wenn alle Schritte erfolgreich sind, andernfalls nil.
    func encodedUrl() -> URL? {        
        // Entferne vorhandene Codierung,
        guard let decodedString = self.removingPercentEncoding,
            // kodiere alle Unicode-Zeichen, damit URLComponents nicht scheitert,
            let unicodeEncodedString = decodedString.addingPercentEncoding(withAllowedCharacters: .urlAllowedCharacters),
            // zerlege in Komponenten, um die richtige Codierung für jeden Teil zu verwenden,
            let components = URLComponents(string: unicodeEncodedString),
            // und re-kodiere, um die Dekodierung wieder rückgängig zu machen, während fehlende Zeichen kodiert werden.
            let percentEncodedUrl = components.url else {
            // Kodierung fehlgeschlagen
            return nil
        }

        return percentEncodedUrl
    }

}

Das kann getestet werden wie folgt:

let urlText = "https://www.example.com//search?q=123&foo=bar&multi=eggs+and+ham&hangul=&spaced=lovely%20spam&illegal=<>#top"
let url = encodedUrl(from: urlText)

Wert von url am Ende: https://www.example.com/%ED%8F%B4%EB%8D%94/search?q=123&foo=bar&multi=eggs+and+ham&hangul=%ED%95%9C%EA%B8%80&spaced=lovely%20spam&illegal=%3C%3E#top

Beachten Sie, dass sowohl die Leerzeichen %20 als auch + erhalten bleiben, Unicode-Zeichen codiert sind, das %20 im ursprünglichen urlText nicht doppelt codiert wird und das Ankerzeichen (Fragment oder #) erhalten bleibt.

Bearbeitung: Überprüfung der Gültigkeit jeder Komponente.

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