我有一个果园网站,并有以下问题:
如果我使用URL:http://asiahotelct.com/tours/ct---chau-%C4%91oc---ha-tien-3n2%C4%91,那没关系.但是当我改变网址/时%2f(如此:http://asiahotelct.com/tours%2fct---chau-%C4%91oc---ha-tien-3n2%C4%91),它就不再适用了.
为什么/不能被取代%2f?
我注意到Wikipedia使用百分比编码作为URL的路径部分,但将%字符转换.为#fragment.
例如,在俄罗斯的"俄罗斯"页面上,第2部分(История)的URL 是
http://ru.wikipedia.org/wiki/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F#.D0.98.D1.81.D1.82.D0.BE.D1.80.D0.B8.D1.8F
代替
http://ru.wikipedia.org/wiki/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F#%D0%98%D1%81%D1%82%D0%BE%D1%80%D0%B8%D1%8F
对于id/name,两者都不是有效的HTML <5令牌,因为令牌必须以[A-Za-z]开头.HTML5 目前声明您可以使用除空格之外的任何字符中的至少一个(因此您根本不需要编码),但维基百科不是HTML5.
那么,为什么维基百科使用这个方案呢?
我能找到的最好的答案是使用XSLT,但我不知道如何将这些答案应用于我的问题.
基本上,DOMDocument在href传递传入的URL(在属性中)方面做得很好,但我实际上是用它来构建一个Twig/Django样式模板,而我宁愿让它们独自存在.这是一个具体的例子,说明了"问题":
<?php
$doc = new DOMDocument();
$doc->loadHTML('<html><body>Test<br><a href="{{variable}}"></a></body></html>');
echo $doc->saveHTML();
Run Code Online (Sandbox Code Playgroud)
其中输出如下:
<html><body>Test<br><a href="%7B%7Bvariable%7D%7D"></a></body></html>
Run Code Online (Sandbox Code Playgroud)
是否有可能href不对属性进行百分比编码?
如果不能直接进行,您能否建议简洁可靠的解决方法?我正在进行其他处理,并且DOMDocument的使用必须保留.那么也许是一个前/后处理技巧?
使用Java,我想剥离片段标识符并执行一组不同URI的简单规范化(例如,小写方案,主机).输入和输出URI在一般HTTP意义上应该是等效的.
通常,这应该是直截了当的.但是,对于像http://blah.org/A_%28Secret%29.xml#blah%这样编码的URI ,(Secret)行为java.util.URI会使生活变得困难.
规范化方法应该http://blah.org/A_%28Secret%29.xml从URI 返回,http://blah.org/A_%28Secret%29.xml并且http://blah.org/A_(Secret).xml在解释中不等同[§2.2; RFC3968 ]
所以我们有以下两种规范化方法:
URI u = new URI("http://blah.org/A_%28Secret%29.xml#blah");
System.out.println(u);
// prints "http://blah.org/A_%28Secret%29.xml#blah"
String path1 = u.getPath(); //gives "A_(Secret).xml"
String path2 = u.getRawPath(); //gives "A_%28Secret%29.xml"
//NORMALISE METHOD 1
URI norm1 = new URI(u.getScheme().toLowerCase(), u.getUserInfo(),
u.getHost().toLowerCase(), u.getPort(), path1,
u.getQuery(), null);
System.out.println(norm1);
// prints "http://blah.org/A_(Secret).xml"
//NORMALISE METHOD 2
URI norm2 = new URI(u.getScheme().toLowerCase(), u.getUserInfo(),
u.getHost().toLowerCase(), u.getPort(), path2,
u.getQuery(), null);
System.out.println(norm2);
// prints "http://blah.org/A_%2528Secret%2529.xml"
Run Code Online (Sandbox Code Playgroud)
如我们所见,在没有片段标识符的情况下解析和重建URI.
但是,对于方法1,u.getPath() …
我需要添加一个链接href="file://attachments/aaaa_#_aaaa.msg"
显然这样做不起作用,因为哈希字符#用于锚点.
所以我尝试将其更改为:href="file://attachments/aaaa_%23_aaaa.msg"
但是当我在IE中打开url时,浏览器正在尝试打开这个:href="file://attachments/aaaa_%2523_aaaa.msg"
IE将%字符编码为%25
如何将文件名放在URL中以编码并读取#所有浏览器中的哈希字符以下载文件?
我无法更改文件名以删除此字符,因此我需要一种方法来处理此问题.
System.out.println(
new URI("http", "example.com", "/servlet", "a=x%20y", null));
Run Code Online (Sandbox Code Playgroud)
结果是http://example.com/servlet?a=x%2520y,查询参数值与提供的值不同.奇怪,但这确实遵循Javadoc:
"百分比字符('%')总是由这些构造函数引用."
我们可以传递解码后的字符串,a=x y然后得到一个合理的(?)结果a=x%20y.
但是如果查询参数值包含"&"字符呢?例如,如果值是具有查询参数的URL本身,则会发生这种情况.看看这个(错误的)查询字符串:
a=b&c.必须在此处转义&符号(a=b%26c),否则这可以被视为查询参数a=b和一些垃圾(c).如果我将它传递给URI构造函数,它会对其进行编码,并返回错误的URL:...?a=b%2526c
这个问题似乎使java.util.URI无用.我在这里错过了什么吗?
java.net.URI确实知道URI的查询部分的存在,但它不了解查询部分的内部,这可能因每个方案而不同.例如,java.net.URI不了解HTTP查询部分的内部结构.如果java.net.URI将查询视为不透明字符串,并且未对其进行更改,则这不会成为问题.但它试图应用一些通用的百分比编码算法,它打破了HTTP URL.
因此,我不能使用URI类从其部分可靠地组装URL,尽管它有构造函数.我还要提到的是,从Java 7开始,相对化操作的实现非常有限,只有当一个URL是另一个URL的前缀时才有效.这两个功能(以及用于这些目的的更精简的界面)是我对java.net.URI感兴趣的原因,但它们都不适合我.
最后,我使用java.net.URL进行解析,并编写代码来汇编部件中的URL并重新激活两个URL.我还检查了Apache HttpClient URIBuilder类,虽然它确实理解了HTTP查询字符串的内部结构,但是从4.3开始,它在处理整个查询部分时遇到了像java.net.URI这样的编码问题.
为什么EscapeDataString在.NET 4和4.5之间表现不同?输出是
Uri.EscapeDataString("-_.!~*'()") => "-_.!~*'()"
Uri.EscapeDataString("-_.!~*'()") => "-_.%21~%2A%27%28%29"
默认情况下,EscapeDataString方法将除RFC 2396非保留字符之外的所有字符转换为十六进制表示形式.如果启用了国际资源标识符(IRI)或国际化域名(IDN)解析,则EscapeDataString方法将除RFC 3986非保留字符之外的所有字符转换为其十六进制表示形式.在转义之前,所有Unicode字符都将转换为UTF-8格式.
作为参考,RFC 2396中的未保留字符定义如下:
unreserved = alphanum | mark
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
(" | ")"
Run Code Online (Sandbox Code Playgroud)
ALPHA / DIGIT / "-" / "." / "_" / "~"
Run Code Online (Sandbox Code Playgroud)
看起来EscapeDataString的每个字符是否被转义都是大致相同的
is unicode above \x7F
? PERCENT ENCODE
: is a percent symbol
? is an escape char
? LEAVE ALONE
: PERCENT ENCODE …Run Code Online (Sandbox Code Playgroud) 很明显,Web服务器必须解码任何转义的未保留字符(例如alphanums等)来进行URI比较.例如,http://www.example.com/~user/index.htm应该相同http://www.example.com/%7Euser/index.htm.
我的问题是,我们要对逃脱的保留字符做什么?
一个例子是%2F,或/.如果%2F请求URI中有一个,那么Web服务器的解析器是否应该用/?替换它?在上面的例子中,它意味着http://www.example.com/~user%2Findex.htm会是一样的http://www.example.com/~user/index.htm吗?虽然我在Apache服务器(2.2.17 Unix)上尝试过它,看起来它给出了"404 Not Found"错误.
这是否意味着%2F其他转义的保留字符应该保持不变(至少在URI比较之前)?
RFC 2616(HTTP 1.1)中有两处提到转义解码问题:
Request-URI以3.2.1节中指定的格式传输.如果使用"%HEX HEX"编码[42]对Request-URI进行编码,则源服务器必须解码Request-URI以正确解释请求.服务器应该使用适当的状态代码响应无效的Request-URI.
和
除"保留"和"不安全"集合之外的字符(参见RFC 2396 [42])等同于它们的"%"HEX HEX"编码.
(根据http://trac.tools.ietf.org/wg/httpbis/trac/ticket/2"unsafe "是一个错误,应从规范中删除.所以我们只看这里的"保留".)
仅供参考,RFC 2396中此类字符的定义:
reserved =";" | "/"| "?" | ":"| "@"| "&"| "="| "+"| "$"| ""
未保留的= alphanum | 标记
mark =" - "| "_"| "" | "!" | "〜"| "*"| "'"| "("|")"
当我使用 window.location 打开带有特殊字符的 url 时,它似乎对特殊字符进行百分比编码,然后打开该 URL。例如
var url = "http://gramfeed.com/instagram/tags/kühl";
window.location = url;
Run Code Online (Sandbox Code Playgroud)
这将导致打开一个带有 URL 的页面:
http://gramfeed.com/instagram/tags/k%C3%BChl
Run Code Online (Sandbox Code Playgroud)
代替:
http://gramfeed.com/instagram/tags/kühl
Run Code Online (Sandbox Code Playgroud)
如何在没有百分比编码字符的情况下正确打开 URL
这是一个使用代码的 jsfiddle:http : //jsfiddle.net/krisrak/aSkMR/
percent-encoding ×10
url ×5
java ×3
uri ×3
escaping ×2
html ×2
.net ×1
.net-4.5 ×1
c# ×1
domdocument ×1
encoding ×1
file-uri ×1
javascript ×1
parsing ×1
php ×1
url-design ×1
xslt ×1