如何对URL字符串进行百分号编码
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何对URL字符串进行百分号编码相关的知识,希望对你有一定的参考价值。
参考技术A 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"
参考技术B 百度UrlEncode编码
原理:编码方法很简单,在该字节ascii码的的16进制字符前面加%. 如 空格字符,ascii码是32,对应16进制是'20',那么urlencode编码结果是:%20
注:采用不同的字符集,编码结果可能不同哈
如何在 C# 中对字符串进行 URL 编码
【中文标题】如何在 C# 中对字符串进行 URL 编码【英文标题】:How to URL encode strings in C# 【发布时间】:2014-03-27 15:46:31 【问题描述】:我们如何在 C# 中使用 URL (RFC 1738) 标准对字符串进行编码?
以下在线工具正在使用此标准 http://www.freeformatter.com/url-encoder.html 转换字符串
我要转换的字符串示例是test(brackets)
,编码后的字符串应如下所示:
test%28brackets%29
【问题讨论】:
URL Encoding using C#的可能重复 【参考方案1】:Uri.EscapeDataString
做你想做的事。见MSDN。
【讨论】:
对不起,它不起作用。试过这个字符串 str = "test(brackets)"; str = Uri.EscapeDataString(str); 奇怪。当我尝试 "string result = Uri.EscapeDataString("test(brackets)");"结果是“test%28brackets%29”。在你的系统上 EscapeDataString 之后 str 有什么值? 字符串保持不变。它不会改变 Uri.EscapeDataString changed with .NET 4.5 包含 RFC 3986 字符的行为。 @Dirk:感谢您提供的信息。事实上,我的目标是 .NET 4.5。【参考方案2】:根据RFC 1738:
Thus, only alphanumerics, the special characters "$-_.+!*'(),", and reserved characters used for their reserved purposes may be used unencoded within a URL.
HttpUtility.UrlEncode
和 WebUtility.UrlEncode
都不会对这些字符进行编码,因为标准规定括号 ()
可以不编码使用。
我不知道您链接的 URL Encoder / Decoder 为什么会对它们进行编码,因为它还将它们列为可在 URL 中使用的字符。
【讨论】:
我正在通过 HTTP 调用第三方 API 并在参数中传递一个字符串。此字符串是 UTF-8 URL 编码的。我的 API 客户端是用 asp.net C# 编写的,而 API 主机可能是用 Java 编写的。当我在字符串参数中有括号/括号 () 之类的字符时,UTF-8 编码器不会对它们进行编码,而 API 主机将它们编码为 %28 和 %29 并且我得到不正确的响应。有什么建议可以解决这个问题吗? API在文档中有如下参考docs.oracle.com/javase/1.5.0/docs/api/java/net/URLEncoder.html 你可以看看这个:***.com/questions/846487/…【参考方案3】:Uri.EscapeDataString
将使用不符合 RFC 1738 的 Uri 标准转换字符串。
RFC 1738 是旧的 URL 标准。
我通过使用FormUrlEncodedContent
完成了它:
data = new List<KeyValuePair<string, string>>();
data.Add(new KeyValuePair<string, string>("key", "value"));
var payloadBody = await new FormUrlEncodedContent(data).ReadAsStringAsync();
如果您不需要编码的 URL body,您可能需要使用键/值 f.e 来欺骗 arround。让值为空。
【讨论】:
以上是关于如何对URL字符串进行百分号编码的主要内容,如果未能解决你的问题,请参考以下文章