문자열을 URL로 인코딩하는 방법


답변:


291

불행히도 stringByAddingPercentEscapesUsingEncoding항상 100 % 작동하지는 않습니다. URL이 아닌 문자를 인코딩하지만 예약 문자 (슬래시 /및 앰퍼샌드 등 &)는 그대로 둡니다. 분명히 이것은 Apple이 알고 있는 버그 이지만 아직 수정하지 않았기 때문에이 범주를 사용하여 문자열을 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 퍼센트가 문자열을 인코딩합니까?
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 /


12
지구상 에서 항상 이스케이프하려는 문자를 명시 적으로 지정할 수있는 CFURLCreateStringByAddingPercentEscapes () 로 드롭 다운하는 대신 이와 같은 복잡한 범주를 사용하는 이유는 무엇입니까?
릴리 발라드

8
CF 함수가 포괄적 인 모델 ( "이 캐릭터를 이스케이프")에서 작동하기 때문에 @KevinBallard ( "이 캐릭터를 이스케이프 처리") – 일반적으로 독점 모델 ( " 이 캐릭터를 제외한 모든 것을 이스케이프")을 사용하려고합니다
Dave DeLong


31
@DaveDeLong 그것이 내가 얻은 곳 일 수 있습니다. 1 년 정도 내 모든 프로젝트에서 표준 범주 였으므로 원래 소스 일 수 있습니다. 나는 문구를 편집하여 글쓰기에 대한 크레딧을 얻는 것처럼 보이지 않습니다).
chown

4
왜? if (thisChar == '') {[출력 appendString : @ "+"]; } 내가 예상 한대로 % 20으로 공백을 인코딩한다면
Chris Stephens

127

도움이 될 수 있습니다.

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 구성 요소의 요구 사항에 따라 허용되는 문자 집합을 선택할 수 있습니다.


7
또한 '&', '?'와 같은 매개 변수 구분 기호를 올바르게 인코딩하지 않습니다. 콘텐츠를 API로 전달하는 경우
벤 Lachman

'&'는 URL 쿼리 문자열 매개 변수에 유효한 문자가 아닙니다. '& amp;'를 사용해보십시오. 대신에.
Nishant

1
stringByAddingPercentEscapesUsingEncoding은 더 이상 사용되지 않습니다. -stringByAddingPercentEncodingWithAllowedCharacters:대신 항상 권장되는 UTF-8 인코딩을 사용하고 각 URL 구성 요소 또는 하위 구성 요소가 어떤 문자가 유효한 지에 대한 규칙이 다르기 때문에 특정 URL 구성 요소 또는 하위 구성 요소를 인코딩하는 대신 사용하십시오 . "
Mihir Oza 17 년

89

답변이 선택된 이후에 새로운 API가 추가되었습니다. 이제 NSURLUtilities를 사용할 수 있습니다. URL의 다른 부분에서는 다른 문자를 사용할 수 있으므로 해당 문자 세트를 사용하십시오. 다음 예제는 쿼리 문자열에 포함되도록 인코딩합니다.

encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];

'&'를 구체적으로 변환하려면 URL 쿼리에서 '&'가 허용되므로 URL 쿼리 세트에서 제거하거나 다른 세트를 사용해야합니다.

NSMutableCharacterSet *chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInRange:NSMakeRange('&', 1)]; // %26
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:chars];

1
"NSURLUtilities 사용"의 의미를 파악하는 데 어느 정도 시간이 걸렸지 만 이제는 iOS 7 및 OS X 10.9에서 Apple이이 새로운 방법을 정의한 NSString 범주의 이름이라는 것을 알았습니다.
Richard Venable 2016 년

1
여기에 더 정교한 답변이 있습니다 : stackoverflow.com/a/20271177/456366
Richard Venable

예. 또한 릴리스 된 새 API 목록에서 NSURLUtilities로 나열되었습니다.
Peter DeWeese

'&'는 물론 쿼리 문자열에서 허용되므로 Richard의 링크를 사용하여 답변을 편집하겠습니다.
Peter DeWeese

3
NSMakeRange('&', 1)Swift는 char없이 int 변환을 허용하지 않기 때문에 Swift에서 작동하지 않습니다. Swift 코드에서이 솔루션을 사용하려면 다음 removeCharactersInString("&")대신 사용하십시오..removeCharactersInRange(...)
cbh2000

16

스위프트 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

  }

}

2
@AlecThomas 당신은 여기에 도착하기 위해 몇 농구대를 뛰어 넘어야하는 것처럼 보입니다. 그래서 확장에서 그것을 숨기는 것이 더 좋습니다
Oliver Atkinson

@OliverAtkinson-나를 위해 Int (String (Character ( "&")))는 nil을 반환합니다. 대신 characters.removeCharactersInString ( "&").
ambientlight

14

iOS 7 업데이트

NSString *encode = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

정확하지 않습니다. URL의 다른 부분을 다르게 이스케이프하고 싶을 것입니다. stackoverflow.com/questions/3423545/…
Steve Moser

실제로 허용되는 문자에 대한 서버에 따라 다릅니다. 여기의 서버 예제에서 허용되는 영숫자 문자 집합 만 사용하면 필요에 따라 특정 문자로 변경할 수 있습니다.
Underdog

1
질문은 '&'문자 인코딩에 대해 묻습니다.
Steve Moser

8

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));

인코딩 공간이 아닙니다. 예를 들어 @ "string string"및 @ "string & string"은 올바르게 인코딩됩니다. 귀하의 의견을 알려주십시오.
Yogesh Lolusare 5

2
이 문제를 해결하는 데 소비 된 대부분의 시간은 거부 기간으로 프레임 워크에 엉망이되지 않고이를 수행하는 'urlencode'와 유사한 이름이 포함되어 있지 않다고 믿지 않았습니다.
dancl

6

모든 경우를 다루는 stringByAddingPercentEncodingWithAllowedCharacters방법 을 사용하십시오.[NSCharacterSet URLUserAllowedCharacterSet]

목표 C

NSString *value = @"Test / Test";
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];

빠른

var value = "Test / Test"
value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())

산출

Test%20%2F%20Test


6

이 주제에 대한 모든 답변과 ( 잘못된 ) 수락 된 답변을 읽은 후 내 기여를 추가하고 싶습니다.

경우 대상은 iOS7에 +이며, 2017 년은 엑스 코드는 빠르고 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]);

디버그 콘솔에 인쇄됩니다.

출처 : I [m] & want (to) break !!! $-> àéìòù-> Dest : I % 27m % 5Bevil % 5D % 26want % 28to % 29break % 21 % 21 % 21 % 24- % 3E % C3 % A0 % C3 % A9 % C3 % AC % C3 % B2 % C3 % B9

... 또한 멀티 스레드 환경에서 다중 초기화를 피하기 위해 dispatch_once를 사용하십시오.


5

다음은 Swift 5.x 의 프로덕션 지원 유연한 접근 방식입니다 .

public extension CharacterSet {

    static let urlQueryParameterAllowed = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&?"))

    static let urlQueryDenied           = CharacterSet.urlQueryAllowed.inverted()
    static let urlQueryKeyValueDenied   = CharacterSet.urlQueryParameterAllowed.inverted()
    static let urlPathDenied            = CharacterSet.urlPathAllowed.inverted()
    static let urlFragmentDenied        = CharacterSet.urlFragmentAllowed.inverted()
    static let urlHostDenied            = CharacterSet.urlHostAllowed.inverted()

    static let urlDenied                = CharacterSet.urlQueryDenied
        .union(.urlQueryKeyValueDenied)
        .union(.urlPathDenied)
        .union(.urlFragmentDenied)
        .union(.urlHostDenied)


    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

미래에 더 나은 답변을 작성하는 방법을 알 수 있도록 귀하의 다운 보트의 이유를 설명하는 의견을 기재하십시오.
Ben Leggiero

4

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/


1
앰퍼샌드, 슬래시 또는 세미콜론은 인코딩하지 않습니다.
Fábio Oliveira

4

이 코드는 특수 문자를 인코딩하는 데 도움이되었습니다.

NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];

3

이 글타래에서 chown 의 objc 답변을 기반으로 한 신속한 코드 .

extension String {
    func urlEncode() -> String {
        return CFURLCreateStringByAddingPercentEscapes(
            nil,
            self,
            nil,
            "!*'();:@&=+$,/?%#[]",
            CFStringBuiltInEncodings.UTF8.rawValue
        )
    }
}

4
이 기능은 iOS 9에서 더 이상 사용되지 않습니다 :(
Oliver Atkinson

3

에서 스위프트 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)
}

2

신속한 3 :

// exclude alpha and numeric == "full" encoding
stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!;

// exclude hostname and symbols &,/ and etc
stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!;

2

10.11 릴리스 노트에서 Apple의 조언은 다음과 같습니다.

전체 URL 문자열을 백분율로 인코딩해야하는 경우이 코드를 사용하여 URL (URLStringToEncode)로 의도 된 NSString을 인코딩 할 수 있습니다.

NSString *percentEncodedURLString =
  [[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];

작동하지 않는 것 같습니다. & 같은 문자는 그대로 남아 있습니다.
kjyv

1

마지막 구성 요소가 아랍어 인 경우에는 다음을 수행했습니다 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) {

      ...
    }

} 

1
-(NSString *)encodeUrlString:(NSString *)string {
  return CFBridgingRelease(
                    CFURLCreateStringByAddingPercentEscapes(
                        kCFAllocatorDefault,
                        (__bridge CFStringRef)string,
                        NULL,
                        CFSTR("!*'();:@&=+$,/?%#[]"),
                        kCFStringEncodingUTF8)
                    );
}

다음 블로그 에 따르면


그러나 iOS 9에서는 더 이상 사용되지 않습니다. 업데이트 된 코드는 무엇입니까?
Sujit Nachan

1

많은 답변이 있지만 효과가 없었으므로 다음을 시도했습니다.

fun simpleServiceCall(for serviceUrl: String, appendToUrl: String) { 
    let urlString: String = serviceUrl + appendToUrl.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!     

    let finalUrl = URL(string: urlString)!

    //continue to execute your service call... 
}

잘하면 그것은 누군가를 도울 것입니다. 감사


0

개별 www 양식 인코딩 쿼리 매개 변수에 대해 NSString에 범주를 만들었습니다.

- (NSString*)WWWFormEncoded{
     NSMutableCharacterSet *chars = NSCharacterSet.alphanumericCharacterSet.mutableCopy;
     [chars addCharactersInString:@" "];
     NSString* encodedString = [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
     encodedString = [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"];
     return encodedString;
}

0

// 이것은 테스트가 없다

NSMutableCharacterSet* set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[set addCharactersInString:@"-_.~"];
NSString *encode = [test stringByAddingPercentEncodingWithAllowedCharacters:set];

0

복잡한 문자열을 POST 매개 변수로 전달하는 비슷한 문제에 직면했습니다. 내 문자열에는 아시아 문자, 공백, 따옴표 및 모든 종류의 특수 문자가 포함될 수 있습니다. 내가 찾은 해결책은 [NSString stringWithFormat : @ "Hu % 04x", [string characterAtIndex : i]]를 사용하여 문자열을 일치하는 일련의 유니 코드로 변환하는 것입니다 (예 : "Hu0040Hu0020Hu03f5 ...."). 원래 문자열의 문자. Java에서도 마찬가지입니다.

이 문자열은 POST 매개 변수로 안전하게 전달 될 수 있습니다.

서버 측 (PHP)에서 모든 "H"를 "\"로 변경하고 결과 문자열을 json_decode로 전달합니다. 마지막 단계는 문자열을 MySQL에 저장하기 전에 작은 따옴표를 이스케이프 처리하는 것입니다.

이 방법으로 서버에 UTF8 문자열을 저장할 수 있습니다.


0

이것은 나를 위해 일하고 있습니다.

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
}

이 링크에서 위 기능을 찾았습니다 : http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/

빠른 확장과 함께이 기능을 사용할 수도 있습니다. 문제가 있으면 알려주세요.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.