web-dev-qa-db-fra.com

Comment puis-je URL encoder une chaîne

J'ai une chaîne d'URL (NSString) avec des espaces et des caractères &. Comment puis-je encoder la chaîne entière (y compris le caractère et les espaces & esperluette)?

180
xonegirlz

Malheureusement, stringByAddingPercentEscapesUsingEncoding ne fonctionne pas toujours à 100%. Il code des caractères non-URL mais laisse les caractères réservés (comme les barres obliques / et esperluette &) seuls. Apparemment, c'est un bug dont Apple a connaissance, mais comme ils ne l'ont pas encore corrigé, j'utilise cette catégorie pour encoder une chaîne dans l'url:

@implementation NSString (NSString_Extended)

- (NSString *)urlencode {
    NSMutableString *output = [NSMutableString string];
    const unsigned char *source = (const unsigned char *)[self UTF8String];
    int sourceLen = strlen((const char *)source);
    for (int i = 0; i < sourceLen; ++i) {
        const unsigned char thisChar = source[i];
        if (thisChar == ' '){
            [output appendString:@"+"];
        } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || 
                   (thisChar >= 'a' && thisChar <= 'z') ||
                   (thisChar >= 'A' && thisChar <= 'Z') ||
                   (thisChar >= '0' && thisChar <= '9')) {
            [output appendFormat:@"%c", thisChar];
        } else {
            [output appendFormat:@"%%%02X", thisChar];
        }
    }
    return output;
}

Utilisé comme ceci:

NSString *urlEncodedString = [@"SOME_URL_GOES_HERE" urlencode];

// Or, with an already existing string:
NSString *someUrlString = @"someURL";
NSString *encodedUrlStr = [someUrlString urlencode];

Cela fonctionne aussi:

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

Quelques bonnes lectures sur le sujet:

Pourcentage iPhone Objective-c pour coder une chaîne?
Encodage d’URL Objective-C et Swift

http://cybersam.com/programming/proper-url-percent-encoding-in-ios
https://devforums.Apple.com/message/15674#15674http://simonwoodside.com/weblog/2009/4/22/how_to_really_url_encode/

283
chown

Cela pourrait être utile

NSString *sampleUrl = @"http://www.google.com/search.jsp?params=Java Developer";
NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
 NSUTF8StringEncoding];

Pour iOS 7+, la méthode recommandée est la suivante:

NSString* encodedUrl = [sampleUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

Vous pouvez choisir le jeu de caractères autorisé selon l'exigence du composant URL.

122
Nishant

De nouvelles API ont été ajoutées depuis la sélection de la réponse. Vous pouvez maintenant utiliser NSURLUtilities. Étant donné que différentes parties des URL autorisent différents caractères, utilisez le jeu de caractères applicable. L'exemple suivant code pour l'inclusion dans la chaîne de requête:

encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];

Pour convertir spécifiquement '&', vous devez le supprimer de l'ensemble de requêtes url ou utiliser un ensemble différent, car '&' est autorisé dans une requête URL:

NSMutableCharacterSet *chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInRange:NSMakeRange('&', 1)]; // %26
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:chars];
89
Peter DeWeese

Exemple Swift 2.0 (compatible iOS 9)

extension String {

  func stringByURLEncoding() -> String? {

    let characters = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet

    characters.removeCharactersInString("&")

    guard let encodedString = self.stringByAddingPercentEncodingWithAllowedCharacters(characters) else {
      return nil
    }

    return encodedString

  }

}
16
Oliver Atkinson

mise à jour iOS 7

NSString *encode = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
14
Underdog

J'ai choisi d'utiliser l'appel CFURLCreateStringByAddingPercentEscapes tel que donné par la réponse acceptée. Toutefois, dans la dernière version de XCode (et IOS), cela a entraîné une erreur. Vous avez donc utilisé les éléments suivants:

NSString *apiKeyRaw = @"79b|7Qd.jW=])(fv|M&W0O|3CENnrbNh4}2E|-)J*BCjCMrWy%dSfGs#A6N38Fo~";

NSString *apiKey = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)apiKeyRaw, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8));
8
Mike Purcell

Essayez d'utiliserstringByAddingPercentEncodingWithAllowedCharactersmethod avec[NSCharacterSet URLUserAllowedCharacterSet]il couvrira tous les cas

Objectif c

NSString *value = @"Test / Test";
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];

Rapide 

var value = "Test / Test"
value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())

Sortie

Test%20%2F%20Test

6
Alex

Après avoir lu toutes les réponses à ce sujet et le ( mauvais ) accepté, je souhaite ajouter ma contribution.

SIla cible est iOS7 +, et en 2017, puisque XCode rend très difficile la compatibilité avec iOS8, le meilleur moyen, avec la sécurité des threads et rapide, AMD prendra totalement en charge le support UTF-8 pour le faire:

(Code objectif C)

@implementation NSString (NSString_urlencoding)

- (NSString *)urlencode {
    static NSMutableCharacterSet *chars = nil;
    static dispatch_once_t pred;

    if (chars)
        return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];

    // to be thread safe
    dispatch_once(&pred, ^{
        chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
        [chars removeCharactersInString:@"!*'();:@&=+$,/?%#[]"];
    });
    return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
}
@end

Cela étend NSString, exclut les caractères interdits RFC, prend en charge les caractères UTF-8 et vous permet d'utiliser des éléments tels que:

NSString *myusername = "I'm[evil]&want(to)break!!!$->àéìòù";
NSLog(@"Source: %@ -> Dest: %@", myusername, [myusername urlencode]);

Cela imprimera sur votre console de débogage:

Source: Je suis [méchant] et je veux faire une pause !!! % A0% C3% A9% C3% AC% C3% B2% C3% B9

... notez également l'utilisation de dispatch_once pour éviter les initialisations multiples dans les environnements multithread.

5
gabry

Utilisez NSURLComponents pour coder les paramètres HTTP GET:

    var urlComponents = NSURLComponents(string: "https://www.google.de/maps/")!
    urlComponents.queryItems = [
        NSURLQueryItem(name: "q", value: String(51.500833)+","+String(-0.141944)),
        NSURLQueryItem(name: "z", value: String(6))
    ]
    urlComponents.URL     // returns https://www.google.de/maps/?q=51.500833,-0.141944&z=6

http://www.ralfebert.de/snippets/ios/encoding-nsurl-get-parameters/

4
Ralf Ebert

Voici une approche flexible prête pour la production dans Swift 4 :

public extension CharacterSet {

    public static let urlQueryParameterAllowed = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&?"))

    public static let urlQueryDenied           = CharacterSet.urlQueryAllowed.inverted()
    public static let urlQueryKeyValueDenied   = CharacterSet.urlQueryParameterAllowed.inverted()
    public static let urlPathDenied            = CharacterSet.urlPathAllowed.inverted()
    public static let urlFragmentDenied        = CharacterSet.urlFragmentAllowed.inverted()
    public static let urlHostDenied            = CharacterSet.urlHostAllowed.inverted()

    public static let urlDenied                = CharacterSet.urlQueryDenied
        .union(.urlQueryKeyValueDenied)
        .union(.urlPathDenied)
        .union(.urlFragmentDenied)
        .union(.urlHostDenied)


    public func inverted() -> CharacterSet {
        var copy = self
        copy.invert()
        return copy
    }
}



public extension String {
    func urlEncoded(denying deniedCharacters: CharacterSet = .urlDenied) -> String? {
        return addingPercentEncoding(withAllowedCharacters: deniedCharacters.inverted())
    }
}

Exemple d'utilisation:

print("Hello, World!".urlEncoded()!)
print("You&Me?".urlEncoded()!)
print("#Blessed 100%".urlEncoded()!)
print("Pride and Prejudice".urlEncoded(denying: .uppercaseLetters)!)

Sortie:

Hello,%20World!
You%26Me%3F
%23Blessed%20100%25
%50ride and %50rejudice
4
Ben Leggiero

Le code Swift basé sur la réponse objc de chown dans ce fil de discussion. 

extension String {
    func urlEncode() -> String {
        return CFURLCreateStringByAddingPercentEscapes(
            nil,
            self,
            nil,
            "!*'();:@&=+$,/?%#[]",
            CFStringBuiltInEncodings.UTF8.rawValue
        )
    }
}
4
neoneye

Ce code m'a aidé pour l'encodage de caractères spéciaux

NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];
3
Rupesh Baldania

Dans Swift 3:

// exclude alpha and numeric == "full" encoding
stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!;

// exclude hostname and symbols &,/ and etc
stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!;
2
sea-kg

Dans Swift 3 , veuillez essayer ci-dessous:

let stringURL = "YOUR URL TO BE ENCODE";
let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(encodedURLString)

Depuis, stringByAddingPercentEscapesUsingEncoding encode les caractères non-URL mais laisse les caractères réservés (comme !*'();:@&=+$,/?%#[]), Vous pouvez encoder l'URL comme le code suivant:

let stringURL = "YOUR URL TO BE ENCODE";
let characterSetTobeAllowed = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)
if let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: characterSetTobeAllowed) {
    print(encodedURLString)
}
2
Dinesh
-(NSString *)encodeUrlString:(NSString *)string {
  return CFBridgingRelease(
                    CFURLCreateStringByAddingPercentEscapes(
                        kCFAllocatorDefault,
                        (__bridge CFStringRef)string,
                        NULL,
                        CFSTR("!*'();:@&=+$,/?%#[]"),
                        kCFStringEncodingUTF8)
                    );
}

selon le blog suivant

1
Anton Kashpor

Dans mon cas où le dernier composant était des lettres arabes, j'ai fait ceci dans Swift 2.2:

extension String {

 func encodeUTF8() -> String? {

    //If I can create an NSURL out of the string nothing is wrong with it
    if let _ = NSURL(string: self) {

        return self
    }

    //Get the last component from the string this will return subSequence
    let optionalLastComponent = self.characters.split { $0 == "/" }.last


    if let lastComponent = optionalLastComponent {

        //Get the string from the sub sequence by mapping the characters to [String] then reduce the array to String
        let lastComponentAsString = lastComponent.map { String($0) }.reduce("", combine: +)


        //Get the range of the last component
        if let rangeOfLastComponent = self.rangeOfString(lastComponentAsString) {
            //Get the string without its last component
            let stringWithoutLastComponent = self.substringToIndex(rangeOfLastComponent.startIndex)


            //Encode the last component
            if let lastComponentEncoded = lastComponentAsString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()) {


            //Finally append the original string (without its last component) to the encoded part (encoded last component)
            let encodedString = stringWithoutLastComponent + lastComponentEncoded

                //Return the string (original string/encoded string)
                return encodedString
            }
        }
    }

    return nil;
}
}

usage:

let stringURL = "http://xxx.dev.com/endpoint/nonLatinCharacters"

if let encodedStringURL = stringURL.encodeUTF8() {

    if let url = NSURL(string: encodedStringURL) {

      ...
    }

} 
1
Bobj-C

J'ai rencontré un problème similaire en passant des chaînes complexes en tant que paramètre POST. Mes chaînes peuvent contenir des caractères asiatiques, des espaces, des guillemets et toutes sortes de caractères spéciaux. La solution que j'ai finalement trouvée consistait à convertir ma chaîne en séries d'unicodes correspondantes, par exemple. "Hu0040Hu0020Hu03f5 ...." avec [NSString stringWithFormat: @ "Hu% 04x", [string characterAtIndex: i]] pour obtenir le code Unicode de chaque caractère de la chaîne d'origine. La même chose peut être faite en Java.

Cette chaîne peut être passée en toute sécurité en tant que paramètre POST.

Du côté du serveur (PHP), je change tous les "H" en "\" et je passe la chaîne résultante à json_decode. La dernière étape consiste à échapper les guillemets simples avant de stocker la chaîne dans MySQL.

De cette façon, je peux stocker n'importe quelle chaîne UTF8 sur mon serveur.

0
Georges

// c'est sans test

NSMutableCharacterSet* set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[set addCharactersInString:@"-_.~"];
NSString *encode = [test stringByAddingPercentEncodingWithAllowedCharacters:set];
0
Achilles Wang

Celui-ci travaille pour moi.

func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? {
    let unreserved = "*-._"
    let allowed = NSMutableCharacterSet.alphanumericCharacterSet()
    allowed.addCharactersInString(unreserved)

    if plusForSpace {
        allowed.addCharactersInString(" ")
    }

    var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed)
    if plusForSpace {
        encoded = encoded?.stringByReplacingOccurrencesOfString(" ",
                                                                withString: "+")
    }
    return encoded
}

J'ai trouvé la fonction ci-dessus à partir de ce lien: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/

Vous pouvez également utiliser cette fonction avec l'extension Swift. S'il vous plaît laissez-moi savoir s'il y a un problème.

0
Gaurav Singla

Pour les paramètres de requête codés par formulaire www individuels, j'ai créé une catégorie sur NSString:

- (NSString*)WWWFormEncoded{
     NSMutableCharacterSet *chars = NSCharacterSet.alphanumericCharacterSet.mutableCopy;
     [chars addCharactersInString:@" "];
     NSString* encodedString = [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
     encodedString = [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"];
     return encodedString;
}
0
Pete Kamm

Le conseil d'Apple, dans les notes de publication de la version 10.11, est le suivant:

Si vous devez coder pour cent une chaîne d'URL entière, vous pouvez utiliser ce code pour coder une chaîne NSString destinée à être une URL (dans urlStringToEncode):

NSString *percentEncodedURLString =
  [[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];
0
nithinbhaktha