我如何URL编码一个string
我有一个空格和&
字符的URLstring( NSString
)。 如何对整个string进行url编码(包括&
符号字符和空格)?
不幸的是, stringByAddingPercentEscapesUsingEncoding
并不总是100%的工作。 它对非URL字符进行编码,但只保留保留字符(如斜杠/
和符号&
)。 显然这是一个苹果知道的错误 ,但由于他们还没有解决这个问题,我一直在使用这个类别来对一个string进行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; }
像这样使用:
NSString *urlEncodedString = [@"SOME_URL_GOES_HERE" urlencode]; // Or, with an already existing string: NSString *someUrlString = @"someURL"; NSString *encodedUrlStr = [someUrlString urlencode];
这也适用:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes( NULL, (CFStringRef)unencodedString, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8 );
关于这个主题的一些很好的阅读
Objective-C的iPhone百分比编码一个string?
Objective-C和Swift URL编码
http://cybersam.com/programming/proper-url-percent-encoding-in-ios
https://devforums.apple.com/message/15674#15674 http://simonwoodside.com/weblog/2009/4/22/how_to_really_url_encode/
这可能会有所帮助
NSString *sampleUrl = @"http://www.google.com/search.jsp?params=Java Developer"; NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
对于iOS 7+,推荐的方法是:
NSString* encodedUrl = [sampleUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
您可以根据URL组件的要求select允许的字符集。
自答案被选定以来,新的API已被添加; 你现在可以使用NSURLUtilities。 由于URL的不同部分允许不同的字符,因此请使用适用的字符集。 下面的示例编码包含在查询string中:
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
要专门转换“&”,您需要将其从url查询集中移除或使用其他url,因为url查询中允许使用“&”:
NSMutableCharacterSet *chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy; [chars removeCharactersInRange:NSMakeRange('&', 1)]; // %26 encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:chars];
Swift 2.0示例(兼容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 } }
ios 7更新
NSString *encode = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
我select使用CFURLCreateStringByAddingPercentEscapes
调用按照接受的答案给出,但是在最新版本的XCode(和IOS)中,它导致了一个错误,所以使用了下面的代码:
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));
尝试与[NSCharacterSet URLUserAllowedCharacterSet]
使用stringByAddingPercentEncodingWithAllowedCharacters
方法它将覆盖所有的情况下
目标C
NSString *value = @"Test / Test"; value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];
迅速
var value = "Test / Test" value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())
产量
Test%20%2F%20Test
swift代码基于chown的objc答案在这个线程中。
extension String { func urlEncode() -> String { return CFURLCreateStringByAddingPercentEscapes( nil, self, nil, "!*'();:@&=+$,/?%#[]", CFStringBuiltInEncodings.UTF8.rawValue ) } }
在阅读了这个主题的所有答案和( 错误 )接受的答案后,我想添加我的贡献。
如果目标是iOS7 +,在2017年它应该是因为XCode真的很难在iOS8下提供兼容性,最好的方式,线程安全,快速,AMD将完整的UTF-8支持做到这一点是:
(目标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
这将扩展NSString,将排除RFC禁止的字符,支持UTF-8字符,并让你使用像这样的东西:
NSString *myusername = "I'm[evil]&want(to)break!!!$->àéìòù"; NSLog(@"Source: %@ -> Dest: %@", myusername, [myusername urlencode]);
这将打印在您的debugging控制台上:
资料来源:我是[邪恶],想要打破!!! $ – >àéìòù – >目的地:%27m%5Bevil%5D%26want%28to%29break%21%21%21%24%3E%C3 %A0%C3%A9%C3%AC%C3%B2%C3%B9
…还要注意使用dispatch_once来避免multithreading环境中的多重初始化。
使用NSURLComponents来编码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/
在Swift 3中 ,请尝试以下内容:
let stringURL = "YOUR URL TO BE ENCODE"; let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) print(encodedURLString)
因为, stringByAddingPercentEscapesUsingEncoding
非URL字符进行编码,但保留字符(如!*'();:@&=+$,/?%#[]
),您可以像下面的代码一样对url进行编码:
let stringURL = "YOUR URL TO BE ENCODE"; let characterSetTobeAllowed = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted) if let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: characterSetTobeAllowed) { print(encodedURLString) }
-(NSString *)encodeUrlString:(NSString *)string { return CFBridgingRelease( CFURLCreateStringByAddingPercentEscapes( kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8) ); }
根据以下博客
在我的情况下,最后一个组件是阿拉伯文字母我做了以下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; } }
用法:
let stringURL = "http://xxx.dev.com/endpoint/nonLatinCharacters" if let encodedStringURL = stringURL.encodeUTF8() { if let url = NSURL(string: encodedStringURL) { ... } }
这段代码帮助我编码特殊字符
NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];
对于单个www表单编码的查询参数,我在NSString上做了一个分类:
- (NSString*)WWWFormEncoded{ NSMutableCharacterSet *chars = NSCharacterSet.alphanumericCharacterSet.mutableCopy; [chars addCharactersInString:@" "]; NSString* encodedString = [self stringByAddingPercentEncodingWithAllowedCharacters:chars]; encodedString = [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"]; return encodedString; }
//这是没有testing
NSMutableCharacterSet* set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy]; [set addCharactersInString:@"-_.~"]; NSString *encode = [test stringByAddingPercentEncodingWithAllowedCharacters:set];
我遇到了一个类似的问题,传递复杂的string作为POST参数。 我的string可以包含亚洲字符,空格,引号和各种特殊字符。 我最终find的解决scheme是将我的string转换为匹配的一系列unicode,例如使用[NSString stringWithFormat:@“Hu%04x”,[stringcharacterAtIndex:i]]从每个Unicode中获取Unicode,例如“Hu0040Hu0020Hu03f5 ….”原始string中的字符。 Java也可以做到这一点。
该string可以作为POST参数安全地传递。
在服务器端(PHP),我将所有“H”更改为“\”,并将结果string传递给json_decode。 最后一步是在将string存储到MySQL之前转义单引号。
这样我可以在我的服务器上存储任何UTF8string。
这个正在为我工作。
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 }
我从这个链接find了上面的函数: http : //useyourloaf.com/blog/how-to-percent-encode-a-url-string/
您也可以使用这个function快速扩展。 请让我知道是否有任何问题。
在迅捷3:
// exclude alpha and numeric == "full" encoding stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!; // exclude hostname and symbols &,/ and etc stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!;
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()) } }
用法示例:
print("Hello, World!".urlEncoded()!) print("You&Me?".urlEncoded()!) print("#Blessed 100%".urlEncoded()!) print("Pride and Prejudice".urlEncoded(denying: .uppercaseLetters)!)
输出:
Hello,%20World! You%26Me%3F %23Blessed%20100%25 %50ride and %50rejudice
苹果公司在10.11版本的build议中提出了如下build议:
如果您需要对整个URLstring进行百分比编码,则可以使用此代码对意图成为URL的url(在urlStringToEncode中)进行编码:
NSString *percentEncodedURLString = [[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];