我的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表单编码的实用程序类”…还有别的办法吗?
如果你的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
URLEncoding可以很好地编码HTTP url,正如您不幸发现的那样。您传入的字符串“http://search.barnesandnoble.com/booksearch/first book.pdf”被正确且完整地编码为url编码的表单。你可以把你得到的整个冗长的字符串作为URL的参数传递回去,它可以被解码成你传递进去的字符串。
听起来,您想要做一些与将整个URL作为参数传递不同的事情。据我所知,你试图创建一个看起来像“http://search.barnesandnoble.com/booksearch/whateverTheUserPassesIn”的搜索URL。你唯一需要编码的是“whateverTheUserPassesIn”位,所以也许你所需要做的就是这样:
String url = "http://search.barnesandnoble.com/booksearch/" +
URLEncoder.encode(userInput,"UTF-8");
这应该会产生一些对你更有效的东西。
除了Carlos Heuberger的回复:
如果需要不同于默认值(80)的参数,则应该使用7参数构造函数:
URI uri = new URI(
"http",
null, // this is for userInfo
"www.google.com",
8080, // port number as int
"/ig/api",
"weather=São Paulo",
null);
String request = uri.toASCIIString();
uri类可以提供帮助;你可以在URL的文档中找到
注意,URI类在某些情况下确实执行组件字段的转义。建议使用URI来管理url的编码和解码
使用一个具有多个参数的构造函数,例如:
URI uri = new URI(
"http",
"search.barnesandnoble.com",
"/booksearch/first book.pdf",
null);
URL url = uri.toURL();
//or String request = uri.toString();
(URI的单参数构造函数不转义非法字符)
上面的代码只转义了非法字符——它不会转义非ascii字符(参见fatih的评论)。
toASCIIString方法可用于获取仅包含US-ASCII字符的String:
URI uri = new URI(
"http",
"search.barnesandnoble.com",
"/booksearch/é",
null);
String request = uri.toASCIIString();
对于像http://www.google.com/ig/api?weather=São Paulo这样的查询URL,使用构造函数的5个参数版本:
URI uri = new URI(
"http",
"www.google.com",
"/ig/api",
"weather=São Paulo",
null);
String request = uri.toASCIIString();