ios swift urlencode

ios - Swift-codificar URL



urlencode (11)

Swift 4

Para codificar un parámetro en la URL, encuentro que usar el carácter .alphanumerics establece la opción más fácil:

let encoded = parameter.addingPercentEncoding(withAllowedCharacters: .alphanumerics) let url = "http://www.example.com/?name=/(encoded!)"

El uso de cualquiera de los conjuntos de caracteres estándar para la codificación de URL (como URLQueryAllowedCharacterSet o URLHostAllowedCharacterSet ) no funcionará, ya que no excluyen los caracteres = o & .

Tenga en cuenta que al usar .alphanumerics codificará algunos caracteres que no necesitan ser codificados (como - , . , _ O ~ -– consulte 2.3. Caracteres no reservados en RFC 3986). Encuentro que usar .alphanumerics más sencillo que construir un conjunto de caracteres personalizado y no me importa que se codifiquen algunos caracteres adicionales. Si eso te molesta, construye un conjunto de caracteres personalizado como se describe en Cómo codificar por porcentaje una cadena de URL , como por ejemplo:

var allowed = CharacterSet.alphanumerics allowed.insert(charactersIn: "-._~") // as per RFC 3986 let encoded = parameter.addingPercentEncoding(withAllowedCharacters: allowed) let url = "http://www.example.com/?name=/(encoded!)"

Advertencia: El parámetro encoded es fuerza desenvuelta. Para una cadena de Unicode inválida podría fallar. Consulte ¿Por qué el valor de retorno de String.addingPercentEncoding () es opcional? . En lugar de desenvolver la fuerza encoded! Puedes usar encoded ?? "" encoded ?? "" o usar if let encoded = ...

Si codifico una cadena como esta:

var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

no escapa a las barras.

He buscado y encontrado este código de Objetivo C:

NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes( NULL, (CFStringRef)unencodedString, NULL, (CFStringRef)@"!*''();:@&=+$,/?%#[]", kCFStringEncodingUTF8 );

¿Hay una forma más fácil de codificar una URL y, de no ser así, cómo escribo esto en Swift?


Swift 4:

Depende de las reglas de codificación seguidas por su servidor.

Apple ofrece este método de clase, pero no informa qué tipo de protocolo RCF sigue.

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!

Siguiendo esta útil tool , debe garantizar la codificación de estos caracteres para sus parámetros:

  • $ (Signo de dólar) se convierte en% 24
  • & (Ampersand) se convierte en% 26
  • + (Plus) se convierte en% 2B
  • , (Coma) se convierte en% 2C
  • : (Colon) se convierte en% 3A
  • ; (Semi-Colon) se convierte en% 3B
  • = (Igual) se convierte en% 3D
  • ? (Signo de interrogación) se convierte en% 3F
  • @ (Commercial A / At) se convierte en% 40

En otras palabras, al hablar sobre la codificación de URL, debe seguir el protocolo RFC 1738 .

Y Swift no cubre la codificación del carácter + char, por ejemplo , pero funciona bien con estos tres @:? caracteres

Entonces, para codificar correctamente cada uno de sus parámetros, la opción .urlHostAllowed no es suficiente, debe agregar también los caracteres especiales como por ejemplo:

encodedParameter = parameter.replacingOccurrences(of: "+", with: "%2B")

Espero que esto ayude a alguien que se vuelva loco para buscar estas informaciones.


Swift 3

En Swift 3 hay addingPercentEncoding

var originalString = "test/test" var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) print(escapedString!)

Salida:

prueba% 2Ftest

Swift 1

En iOS 7 y superior hay stringByAddingPercentEncodingWithAllowedCharacters

var originalString = "test/test" var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) println("escapedString: /(escapedString)")

Salida:

prueba% 2Ftest

Los siguientes son juegos de caracteres útiles (invertidos):

URLFragmentAllowedCharacterSet "#%<>[/]^`{|} URLHostAllowedCharacterSet "#%/<>?@/^`{|} URLPasswordAllowedCharacterSet "#%/:<>?@[/]^`{|} URLPathAllowedCharacterSet "#%;<>?[/]^`{|} URLQueryAllowedCharacterSet "#%<>[/]^`{|} URLUserAllowedCharacterSet "#%/:<>?@[/]^`

Si desea que se escape un conjunto diferente de caracteres, cree un conjunto:
Ejemplo con el carácter "=" añadido:

var originalString = "test/test=42" var customAllowedSet = NSCharacterSet(charactersInString:"=/"#%/<>?@//^`{|}").invertedSet var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedSet) println("escapedString: /(escapedString)")

Salida:

prueba% 2Ftest% 3D42

Ejemplo para verificar caracteres ascii que no están en el conjunto:

func printCharactersInSet(set: NSCharacterSet) { var characters = "" let iSet = set.invertedSet for i: UInt32 in 32..<127 { let c = Character(UnicodeScalar(i)) if iSet.longCharacterIsMember(i) { characters = characters + String(c) } } print("characters not in set: /'/(characters)/'") }


Swift 3:

let originalString = "http://www.ihtc.cc?name=htc&title=iOS开发工程师"

1. encodingQuery:

let escapedString = originalString.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)

resultado:

"http://www.ihtc.cc?name=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88"

2. encodingURL:

let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

resultado:

"http:%2F%2Fwww.ihtc.cc%3Fname=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88"


Este está trabajando para mí.

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 }

Encontré la función anterior en este enlace: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/ .


Esto está funcionando para mí en Swift 4.2. El caso de uso es tomar una URL del portapapeles o similar que puede que ya tenga caracteres de escape pero que también contenga caracteres Unicode que podrían hacer que la URL(string:) falle.

func encodedUrl(from string: String) -> URL? { // Remove preexisting encoding guard let decodedString = string.removingPercentEncoding, // Reencode, to revert decoding while encoding missed characters let percentEncodedString = decodedString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { // Coding failed return nil } // Create URL from encoded string, or nil if failed return URL(string: percentEncodedString) } let urlText = "https://www.example.com/폴더/search?q=123&foo=bar&multi=eggs+and+ham&hangul=한글&spaced=lovely%20spam&illegal=<>" let url = encodedUrl(from: urlText)

Valor de url al final: https://www.example.com/%ED%8F%B4%EB%8D%94/search?q=123&foo=bar&multi=eggs+and+ham&hangul=%ED%95%9C%EA%B8%80&spaced=lovely%20spam&illegal=%3C%3E

Tenga en cuenta que tanto el espaciado de %20 como el de + se conservan, los caracteres de Unicode se codifican y el %20 en el urlText original no se codifica doble.

Advertencia: este es un acceso directo, ya que usa .urlQueryAllowed en toda la URL; también asume que la URL ya estaba funcionando en un navegador. ¡Usa sabiamente! También estoy abierto a sugerencias (no llegué a cortar la URL completa con los componentes de URLComponents , aplicar conjuntos de caracteres individuales y volver a ensamblar).


Puede usar URLComponents para evitar tener que escapar manualmente el porcentaje de su cadena de consulta:

let scheme = "https" let host = "www.google.com" let path = "/search" let queryItem = URLQueryItem(name: "q", value: "Formula One") var urlComponents = URLComponents() urlComponents.scheme = scheme urlComponents.host = host urlComponents.path = path urlComponents.queryItems = [queryItem] if let url = urlComponents.url { print(url) // "https://www.google.com/search?q=Formula%20One" }

extension URLComponents { init(scheme: String, host: String, path: String, queryItems: [URLQueryItem]) { self.init() self.scheme = scheme self.host = host self.path = path self.queryItems = queryItems } } if let url = URLComponents(scheme: "https", host: "www.google.com", path: "/search", queryItems: [URLQueryItem(name: "q", value: "Formula One")]).url { print(url) // https://www.google.com/search?q=Formula%20One }


Swift 3:

let allowedCharacterSet = (CharacterSet(charactersIn: "!*''();:@&=+$,/?%#[] ").inverted) if let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) { //do something with escaped string }


Todo es igual

var str = CFURLCreateStringByAddingPercentEscapes( nil, "test/test", nil, "!*''();:@&=+$,/?%#[]", CFStringBuiltInEncodings.UTF8.rawValue ) // test%2Ftest


Yo mismo lo necesitaba, así que escribí una extensión de String que permite tanto URLEncoding strings, como el objetivo final más común, al convertir un diccionario de parámetros en los parámetros de URL de estilo "GET":

extension String { func URLEncodedString() -> String? { var escapedString = self.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) return escapedString } static func queryStringFromParameters(parameters: Dictionary<String,String>) -> String? { if (parameters.count == 0) { return nil } var queryString : String? = nil for (key, value) in parameters { if let encodedKey = key.URLEncodedString() { if let encodedValue = value.URLEncodedString() { if queryString == nil { queryString = "?" } else { queryString! += "&" } queryString! += encodedKey + "=" + encodedValue } } } return queryString } }

¡Disfrutar!


Swift 4 (no probado, por favor, comenta si funciona o no. Gracias a @sumizome por sugerencia)

var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed allowedQueryParamAndKey.remove(charactersIn: ";/?:@&=+$, ") paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

Swift 3

let allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed.remove(charactersIn: ";/?:@&=+$, ") paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

Swift 2.2 (Préstamo de Zaph y corrección de la clave de consulta url y los valores de los parámetros)

var allowedQueryParamAndKey = NSCharacterSet(charactersInString: ";/?:@&=+$, ").invertedSet paramOrKey.stringByAddingPercentEncodingWithAllowedCharacters(allowedQueryParamAndKey)

Ejemplo:

let paramOrKey = "https://some.website.com/path/to/page.srf?a=1&b=2#top" paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey) // produces: "https%3A%2F%2Fsome.website.com%2Fpath%2Fto%2Fpage.srf%3Fa%3D1%26b%3D2%23top"

Esta es una versión más corta de la respuesta de Bryan Chen. Supongo que urlQueryAllowed permite que los caracteres de control estén bien, a menos que formen parte de la clave o el valor de la cadena de consulta en el punto en el que deben escaparse.