美文网首页iOS 提升
iOS URL编码和URL拼接(如含中文等特殊符号).md

iOS URL编码和URL拼接(如含中文等特殊符号).md

作者: 儒徒 | 来源:发表于2021-01-29 16:21 被阅读0次
    • URL编码默认使用的字符集是US-ASCII.对于非ASCII字符, 需要使用ASCII字符集的超级进行编码.
    • URL中只允许包含4种字符:
    英文字符 : a-zA-Z
    数字: 0-9
    -_.~ 4个特殊字符.
    保留字符: ! * ' ( ) ; : @ & = + $ , / ? # [ ]
    
    

    URL编码使用%其后跟随两位(中文是三位)的十六进制数来替换非ASCII字符,
    不能在URL中包含任何非ASCII字符, 如中文字符等.

    基本的NSURL

    NSString *urlString = @"https://www.baidu.com";
    NSURL *url = [NSURL URLWithString:urlString];
    

    但是, 若urlString中含有中文等非URL允许的字符时, 创建的NSURL对象为nil.

    iOS 7之后: stringByAddingPercentEncodingWithAllowedCharacters

    NSString *latestUrl = @"https://www.baidu.com?name=小明&age=20";
    
    latestUrl = [[latestUrl copy] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    
    ///https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20
    
    NSString *originUrlString = @"https://www.baidu.com/百度?name=小明&age=20";
    NSString *encode_fragment = [[originUrlString copy] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSCharacterSet *encode_fragment_invertedSet = [NSCharacterSet URLQueryAllowedCharacterSet].invertedSet;
    NSString *encode_fragment_invertedString = [[originUrlString copy] stringByAddingPercentEncodingWithAllowedCharacters:encode_fragment_invertedSet];
    /**
     encode_fragment:
     https://www.baidu.com/%E7%99%BE%E5%BA%A6?name=%E5%B0%8F%E6%98%8E&age=20
     
     encode_fragment_invertedString
     %68%74%74%70%73%3A%2F%2F%77%77%77%2E%62%61%69%64%75%2E%63%6F%6D%2F%E7%99%BE%E5%BA%A6%3F%6E%61%6D%65%3D%E5%B0%8F%E6%98%8E%26%61%67%65%3D%32%30
     */
    
    /**
    
     URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
    
     URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
    
     URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
    
     URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
    
     URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
    
     URLUserAllowedCharacterSet      "#%/:<>?@[\]^`
    
     */
    
    ///自定义的字符集. 如(带空格): [NSCharacterSet characterSetWithCharactersInString:@"#%/!*'\"();:@&=+$,[]? "]
    
    NSString *latestUrl_2 = @"https://www.baidu.com?name=小明&age=20";
    
    NSCharacterSet *defaultCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"?&=/ "];
    
    if (defaultCharacterSet) {
    
        NSString *latestUrl_2_defaultAllow = [[latestUrl_2 copy] stringByAddingPercentEncodingWithAllowedCharacters:defaultCharacterSet];
    
        /**
    
         %68%74%74%70%73%3A//%77%77%77%2E%62%61%69%64%75%2E%63%6F%6D?%6E%61%6D%65=%E5%B0%8F%E6%98%8E&%61%67%65=%32%30
    
         可以看出除了?&=/ ,其他字符都被编码了.
    
         */
    
    
    
        //invertSet
    
        NSCharacterSet *invertCharacterSet = defaultCharacterSet.invertedSet;
    
        latestUrl_2 = [[latestUrl_2 copy] stringByAddingPercentEncodingWithAllowedCharacters:invertCharacterSet];
    
        /**
    
         https:%2F%2Fwww.baidu.com%3Fname%3D%E5%B0%8F%E6%98%8E%26age%3D20
    
         */
    
    }
    
    /// 服务端会对请求进行UTF-8解码一次,请确保请求中的字符只进行一次UTF-8编码。
    
    
    

    URL中含有中文并且拼接额外参数

    NSString *originUrlString = @"https://www.baidu.com?name=小明&age=20";
    
    
    
    
    
    //需要拼接的参数:转为通过&拼接
    
    NSMutableDictionary *urlParamsDic = [NSMutableDictionary dictionary];
    
    [urlParamsDic setValue:@"22" forKey:@"sex"];
    
    [urlParamsDic setValue:@"one" forKey:@"class"];
    
    __block NSMutableString *joinStr = [NSMutableString string];
    
    if (urlParamsDic && [urlParamsDic isKindOfClass:[NSDictionary class]] && urlParamsDic.count) {
    
        
    
        [urlParamsDic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
    
            if (key && obj) {
    
                [joinStr appendFormat:@"%@=%@&",key,obj];
    
            }
    
        }];
    
        if ([joinStr hasSuffix:@"&"]) {
    
            [joinStr deleteCharactersInRange:NSMakeRange(joinStr.length-1, 1)];
    
        }
    
    }
    
    ///joinStr = sex=22&class=one
    
    
    
    /**
    
     *url中含有中文,先对其encode生成NSURL
    
     * 拼接后再decode,最后再对拼接后的encode
    
     */
    
    //1.encode生成NSURL
    
    NSURL *originUrl = [NSURL URLWithString:[originUrlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
    
    ///originUrl = https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20
    
    //2.在url后拼接参数
    
    NSString *latestURLString = @"";
    
    BOOL cointainQuery = NO;
    
    if (joinStr.length == 0 || [originUrl.query rangeOfString:joinStr].location != NSNotFound) {
    
        //其中,若joinStr = 0则表示默认包含该空字符串
    
        cointainQuery = YES;///
    
    }
    
    
    
    if (cointainQuery) {
    
        latestURLString = originUrl.absoluteString;
    
    }else{
    
        ///originUrl.query: name=%E5%B0%8F%E6%98%8E&age=20
    
        if (originUrl.query.length>0) {
    
            latestURLString = [NSString stringWithFormat:@"%@&%@", originUrl.absoluteString,joinStr];
    
            ///https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20&sex=22&class=one
    
        }else{
    
            BOOL hasSuffix = [originUrl.absoluteString hasSuffix:@"?"];
    
            latestURLString = [NSString stringWithFormat:@"%@%@%@",originUrl.absoluteString, hasSuffix ? @"":@"?", joinStr];
    
        }
    
    }
    
    ///
    
    //3.拼接后decode
    
    latestURLString = [latestURLString stringByRemovingPercentEncoding];
    
    ///latestURLString = https://www.baidu.com?name=小明&age=20&sex=22&class=one
    
    ///
    
    //4.最后对对接后的encode
    
    latestURLString =  [latestURLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    
    ///latestURLString =https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20&sex=22&class=one
    
    NSLog(@"%@",latestURLString);
    
    
    

    相关文章

      网友评论

        本文标题:iOS URL编码和URL拼接(如含中文等特殊符号).md

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