你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 如何對URL字符串進行百分號編碼

如何對URL字符串進行百分號編碼

編輯:IOS開發基礎

47.png

  • 原文:How to percent encode a URL String

  • 作者:@kharrison

  • 譯者:CocoaChina--飄


在和web服務進行交互時,我們經常需要對URL中的特定字符和傳輸的表單數據進行百分號編碼。例如,’&’在百分號編碼時會變成’%26’。搞清楚 URL中哪部分的哪些字符應該進行百分號編碼了並不是件易事。最好的資料好像是RFC 3986和W3C HTML5。出於興趣和教育目的,我創建了swift的String的擴展(和作為對比的Objective-C的分類)。

RFC3986 編碼查詢字符串

在 RFC3986 的第2.3節列出了你不需要百分號編碼的字符,因為它們在URL中沒有特殊的含義。

ALPHA / DIGIT / “-” / “.” / “_” / “~” 

α/數字/”-”/”.”/”_”

第3.4節也解釋了因為查詢往往會本身包含一個URL,最好不要百分號編碼斜槓(“/”)和問號(“?”)。這也是受歡迎的iOS HTTP網絡庫Alamofire采取的方法,這給了我信心。

因此,用RFC 3986編碼一個兼容性的查詢,我們可以百分號編碼如上所述以外的所有字符。這很簡單,如果我們首先構建一組允許的字符,然後用stringByAddingPercentEncodingWithAllowedCharacters去編碼剩余的。

注意:蘋果已經在iOS 9中棄用了stringByAddingPercentEscapesUsingEncoding或CFURLCreateStringByAddingPercentEscapes這兩個方法。

Swift

首先,swift String extension:

extension String {
    func stringByAddingPercentEncodingForRFC3986() -> String? {
        let unreserved = "-._~/?"
        let allowed = NSMutableCharacterSet.alphanumericCharacterSet()
        allowed.addCharactersInString(unreserved)
        return stringByAddingPercentEncodingWithAllowedCharacters(allowed)
    }
}

Object-C

我們可以用Object-C的NSString的分類來做相同的事。

@implementation NSString (URLEncoding)
- (nullable NSString *)stringByAddingPercentEncodingForRFC3986 {
    NSString *unreserved = @"-._~/?";
    NSMutableCharacterSet *allowed = [NSMutableCharacterSet alphanumericCharacterSet];
    [allowed addCharactersInString:unreserved];
    return [self stringByAddingPercentEncodingWithAllowedCharacters: allowed];
}
@end

用例

// Swift 
let query = "one&two =three" 
let encoded = query.stringByAddingPercentEncodingForRFC3986() 
// "one%26two%20%3Dthree"  

// Objective-C 
NSString *query = @"one&two =three"; 
NSString *encoded = [query stringByAddingPercentEncodingForRFC3986]; 
// "one%26two%20%3Dthree"

對x-www-form-urlencoded進行編碼

推薦W3C HTML5 對表單數據編碼是相似的,但是和RFC 3986有一點不同。在第4.10.22.5節中告訴我們下列字符是不應該百分號編碼:

ALPHA / DIGIT / “*” / “-” / “.” / “_” 

α/數字/”-”/”.”/”_”

你應該用“+”(0x2B)代替空格(“ ”)。它和RFC 3986 的不同在 Stack Overflow answer 裡有描述。波浪號(“~”)被百分號編碼了,但是星號(“*”)沒有。該建議很好地總結了這種情況:這種編碼的表單數據在很多方面是異常的,多年來的實踐的問題和折中解決導致了互通性的一系列必要操作。但是絕不代表好的設計實踐。

Swift

給String extension添加一個新的方法

public 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
}

注意,由於很多 web服務好像不關心我用“+”或者百分號編碼將空格做了可選的編碼。

Object-C

Object-C的方法缺少一個可選參數

- (nullable NSString *)stringByAddingPercentEncodingForFormData:(BOOL)plusForSpace
{
    NSString *unreserved = @"*-._";
    NSMutableCharacterSet *allowed = [NSMutableCharacterSet                                     alphanumericCharacterSet];
    [allowed addCharactersInString:unreserved];
    if (plusForSpace) {
        [allowed addCharactersInString:@" "];
    }
    NSString *encoded = [self stringByAddingPercentEncodingWithAllowedCharacters:allowed];
    if (plusForSpace) {
        encoded = [encoded stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    }
    return encoded;
}

用例:

// Swift
let query = "one two"
let space = query.stringByAddingPercentEncodingForFormData()
// "one%20two"

let plus = query.stringByAddingPercentEncodingForFormData(true)
// "one+two"

// Objective-C
NSString *query = @"one two";
NSString *encodedQuery = [query stringByAddingPercentEncodingForFormData:YES];
// "one+two"

源代碼

Swift代碼和一些測試用例你可以在我的Github代碼實例庫的Encode項目裡找到,Object-C的分類和測試用例在TwitterSearch項目裡。歡迎反饋和改進。

深入閱讀

  • 百分號編碼(維基百科)

  • RFC 3986同一資源標識符(URI):通用語法

  • W3C HTML5 見第4.10.22.6 節URL表單數據的編碼

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved