美文网首页iOS - Developer - OC 进阶大全
URL 编码:stringByAddingPercentEsca

URL 编码:stringByAddingPercentEsca

作者: 超_iOS | 来源:发表于2018-01-04 17:02 被阅读101次

    URL编码问题,这个文章不错:

    别再使用stringByAddingPercentEscapesUsingEncoding

    当遇到发送网络请求的参数中有汉字的情况,很多人一股脑地使用stringByAddingPercentEscapesUsingEncoding:进行转义,这样带有汉字的urlString就会将每个汉字转成相应的unicode编码对应的3个%形式,这叫urlEncode(每个能写后端的语言都有的方法),但是苹果的stringByAddingPercentEscapesUsingEncoding:却不是urlEncode。实际上我们使用的参数值可能会包含一些特殊的字符,如&,?这样的字符,而Percent转义已经不能满足需求了,如下面的例子:

    NSString *queryWord = @"汉字&ss";
    NSString *urlString = [NSString stringWithFormat:@"https://www.baidu.com/s?ie=UTF-8&wd=%@", queryWord];
    NSString *escapedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@", escapedString); // https://www.baidu.com/s?ie=UTF-8&wd=%E6%B1%89%E5%AD%97&ss
    

    这是一个非常常见的情景,(之前公司项目的搜索中,也遇到过这种情况),这种被转义之后的URL,服务端接收到的参数会使这样的

    ["ie":"UTF-8", "wd":"汉字", "ss":nil]
    即使你做如下的改进:(在请求之前将每个参数都转义,再使用&拼接参数也无济于事)

    NSString *queryWord = @"汉字&ss";
    NSString *escapedQueryWord = [queryWord stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSString *urlString = [NSString stringWithFormat:@"https://www.baidu.com/s?ie=UTF-8&wd=%@", escapedQueryWord];
    NSLog(@"%@", urlString); // https://www.baidu.com/s?ie=UTF-8&wd=%E6%B1%89%E5%AD%97&ss
    

    产生这种情况的原因是:百分号转义不等于URLEncode
    该编码不同于URL编码,由于不会对&字符编码,因此不会改变URL参数的分隔。URL编码会编码&、?与其他标点符号。如果查询字符串包含了这些字符,那么需要实现一种更加彻底的编码方法。

    不过还好iOS7.0推出了stringByAddingPercentEncodingWithAllowedCharacters:方法

    这个方法会对字符串进行更彻底的转义,但是需要传递一个参数:这个参数是一个字符集,表示:在进行转义过程中,不会对这个字符集中包含的字符进行转义,而保持原样保留下来。
    这样就可以使用它改造上面的代码了:

    NSString *queryWord = @"汉字&ss";
    NSString *escapedQueryWord = [queryWord stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet letterCharacterSet]];
    NSLog(@"%@", escapedQueryWord); // %E6%B1%89%E5%AD%97%26ss
    NSString *urlString = [NSString stringWithFormat:@"https://www.baidu.com/s?ie=UTF-8&wd=%@", escapedQueryWord];
    NSLog(@"%@", urlString); // https://www.baidu.com/s?ie=UTF-8&wd=%E6%B1%89%E5%AD%97%26ss
    

    在上面的例子中传递参数[NSCharacterSet letterCharacterSet]来保证字母不被转义。所以被转义之后的参数值是:%E6%B1%89%E5%AD%97%26ss,这样问题就解决了,但是有时候会遇到queryString中的表单域也需要转义的情况,比如是一个表单数组如:

    https://www.baidu.com/s?person[contact]=13801001234&person[address]=北京&habit[]=游泳&habit[]=骑行
    

    这样可以使用将key转义,不过key中的[和]字符是不需要转义的:可以自定义一个CharacterSet实现需求:

    NSMutableCharacterSet *mutableCharSet = [[NSMutableCharacterSet alloc] init];
    [mutableCharSet addCharactersInString:@"[]"]; // 允许'['和']'不被转义
    NSCharacterSet *charSet = mutableCharSet.copy;
    
    NSMutableString *mutableString = [NSMutableString string];
    for (unit in queryString) {
        NSString *escapedField = [unit.field stringByAddingPercentEncodingWithAllowedCharacters:charSet];
        NSString *escapedValue = [unit.value stringByAddingPercentEncodingWithAllowedCharacters:charSet];
        [mutableString addFormat:@"%@=%@", escapedField, escapedValue];
    }
    

    这样问题已经圆满解决了,美中不足的是:当queryString非常多的时候你如何保证从queryString正确地提取出来每个unit呢,这个牵扯到复杂的字符串解析的问题。先不做讨论。

    下面还有对AFN的分析,就不贴了.
    http://www.cnblogs.com/Mike-zh/p/5152073.html

    URL编码:

     NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:urlStr]invertedSet];//非URLstr字符集
        
        NSString *encodedUrl = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];//对非URLstr字符集编码
    

    相关文章

      网友评论

        本文标题:URL 编码:stringByAddingPercentEsca

        本文链接:https://www.haomeiwen.com/subject/lcarnxtx.html