我的Java独立应用程序从用户那里获得一个URL(指向一个文件),我需要点击它并下载它。我面临的问题是,我不能正确编码HTTP URL地址…
例子:
URL: http://search.barnesandnoble.com/booksearch/first book.pdf
java.net.URLEncoder.encode(url.toString(), "ISO-8859-1");
回报我。
http%3A%2F%2Fsearch.barnesandnoble.com%2Fbooksearch%2Ffirst+book.pdf
但是,我想要的是
http://search.barnesandnoble.com/booksearch/first%20book.pdf
(空格替换为%20)
我猜URLEncoder不是为编码HTTP url设计的…JavaDoc说“HTML表单编码的实用程序类”…还有别的办法吗?
我开发了一个用于此目的的库:galimatias。它解析URL的方式与web浏览器相同。也就是说,如果一个URL在浏览器中工作,它将被galimatias正确解析。
在这种情况下:
// Parse
io.mola.galimatias.URL.parse(
"http://search.barnesandnoble.com/booksearch/first book.pdf"
).toString()
会给你:http://search.barnesandnoble.com/booksearch/first%20book.pdf。当然,这是最简单的情况,但它可以用于任何东西,远远超出java.net.URI。
你可以在https://github.com/smola/galimatias上查看
如果你的URL中有一个编码的“/”(%2F),这仍然是一个问题。
RFC 3986 -章节2.2说:“如果URI组件的数据与保留字符作为分隔符的目的相冲突,那么冲突的数据必须在URI形成之前进行百分比编码。”(rfc3986 -第2.2节)
但是Tomcat有一个问题:
http://tomcat.apache.org/security-6.html - Fixed in Apache Tomcat 6.0.10
important: Directory traversal CVE-2007-0450
Tomcat permits '\', '%2F' and '%5C'
[...] .
The following Java system properties
have been added to Tomcat to provide
additional control of the handling of
path delimiters in URLs (both options
default to false):
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH:
true|false
org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH:
true|false
Due to the impossibility to guarantee
that all URLs are handled by Tomcat as
they are in proxy servers, Tomcat
should always be secured as if no
proxy restricting context access was
used.
Affects: 6.0.0-6.0.9
因此,如果您有一个含有%2F字符的URL, Tomcat将返回:"400 Invalid URI: noSlash"
你可以在Tomcat启动脚本中切换bug修复:
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
如果你有一个URL,你可以将URL . tostring()传递给这个方法。首先解码,以避免双重编码(例如,编码空格会得到%20,编码百分号会得到%25,因此双重编码将把空格变成%2520)。然后,像上面解释的那样使用URI,添加URL的所有部分(这样就不会删除查询参数)。
public URL convertToURLEscapingIllegalCharacters(String string){
try {
String decodedURL = URLDecoder.decode(string, "UTF-8");
URL url = new URL(decodedURL);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
return uri.toURL();
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}