urlEncode,主要是为了让url的参数可以被准确无误的传输
字符串数据以url的形式传递给web服务器时,对字符是有限制的。为了符合url的规范,这些被限制的字符,就需要被转义。比方说:把一个邮箱放入url就需要转义,因为邮箱中包含限制字符@
。
在标准的url规范中,中文和很多的字符是不允许出现在url中的。这些需要转义的字符都将被替换成%
后跟两位十六进制数。
哪些字符需要转义
1、ASCII的控制字符
这些字符都是不可打印的,自然需要进行转化。
2、一些特殊字符
例如:emoji字符,转化也是理所当然的。
3、与url分隔字符相同的字符
url中的分隔符包含主要分隔符:#[]@?/
和次要分隔符!$&'()*+,;=
。对于url的query
参数和值,如果在分隔符的包含范围内,除了?
和/
外,都需要转义。例如:对于原始urlhttps://www.baidu.com?paramA=哈哈¶mB=&
来说,哈哈
和paramB=&
中的&
就需要参与转义。否则,对于&
来说,你认为它是一个参数值,还是url本身的分隔符呢?
4、一些不安全的字符
例如:空格。为了避免歧义,需要被转化成+
或者%20
。具体转换成+
还是%20
主要依据不同的转换标准。
AFURLRequestSerialization的转义过程
AFURLRequestSerialization
的源码很好地说明了转义的过程和规则:
//对string进行url转义
NSString * AFPercentEscapedStringFromString(NSString *string) {
//需要参与参与转义的分隔符
static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;=";//子分隔符
//从query参数可用的字符集中把:#[]@和!$&'()*+,;=去除,得到不用参与转义的字符集
NSMutableCharacterSet *allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
[allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]];
static NSUInteger const batchSize = 50;//每次转码的最大长度,修复对超长中文字符串转义会导致闪退的问题
NSUInteger index = 0;
NSMutableString *escaped = @"".mutableCopy;
while (index < string.length) {
NSUInteger length = MIN(string.length - index, batchSize);
NSRange range = NSMakeRange(index, length);
// 等emoji的长度不是一,为了避免原来的range切断emoji,对原来range扩展一下
range = [string rangeOfComposedCharacterSequencesForRange:range];
NSString *substring = [string substringWithRange:range];
NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];//除了不用参与转义的字符,其他字符都应该参与转义
[escaped appendString:encoded];
index += range.length;
}
return escaped;
}