我的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表单编码的实用程序类”…还有别的办法吗?
在此我将针对Android用户添加一条建议。您可以这样做,从而避免获得任何外部库。此外,上面一些答案中建议的所有搜索/替换字符解决方案都是危险的,应该避免。
试一试:
String urlStr = "http://abc.dev.domain.com/0007AC/ads/800x480 15sec h.264.mp4";
URL url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
url = uri.toURL();
您可以看到,在这个特定的URL中,我需要对这些空格进行编码,以便我可以将其用于请求。
这利用了Android类中提供给你的几个功能。首先,URL类可以将URL分解为适当的组件,因此不需要进行任何字符串搜索/替换工作。其次,当您通过组件而不是从单个字符串构造URI时,这种方法利用了正确转义组件的URI类特性。
这种方法的美妙之处在于,您可以使用任何有效的url字符串并让它工作,而不需要您自己对它有任何特殊的了解。
请注意,上面的大部分答案都是不正确的。
URLEncoder类,不管它的名字,不是这里需要的。不幸的是,Sun给这个类命名得如此烦人。URLEncoder用于作为参数传递数据,而不是用于对URL本身进行编码。
换句话说,“http://search.barnesandnoble.com/booksearch/first book.pdf”是URL。参数可以是,例如,“http://search.barnesandnoble.com/booksearch/first book.pdf?parameter1=this¶m2=that”。参数是你使用URLEncoder的目的。
下面两个例子强调了两者之间的区别。
根据HTTP标准,下面会产生错误的参数。注意&号(&)和加号(+)编码错误。
uri = new URI("http", null, "www.google.com", 80,
"/help/me/book name+me/", "MY CRZY QUERY! +&+ :)", null);
// URI: http://www.google.com:80/help/me/book%20name+me/?MY%20CRZY%20QUERY!%20+&+%20:)
下面的代码将生成正确的参数,并对查询进行正确编码。注意空格、&号和加号。
uri = new URI("http", null, "www.google.com", 80, "/help/me/book name+me/", URLEncoder.encode("MY CRZY QUERY! +&+ :)", "UTF-8"), null);
// URI: http://www.google.com:80/help/me/book%20name+me/?MY+CRZY+QUERY%2521+%252B%2526%252B+%253A%2529
我同意马特的观点。事实上,我从未在教程中看到过很好的解释,但一个问题是如何编码URL路径,另一个非常不同的问题是如何编码附加到URL的参数(“?”符号后面的查询部分)。它们使用类似的编码,但并不相同。
专门用于空白字符的编码。URL路径需要编码为%20,而查询部分允许使用%20和“+”符号。最好的方法是使用Web浏览器对我们的Web服务器进行测试。
对于这两种情况,我总是会编码组件组件,而不是整个字符串。实际上URLEncoder允许查询部分这样做。对于路径部分,您可以使用类URI,尽管在本例中它要求整个字符串,而不是单个组件。
无论如何,我相信避免这些问题的最好方法是使用个人无冲突的设计。怎么做?例如,我从来不使用a-Z, a-Z, 0-9和_以外的字符命名目录或参数。这样,唯一需要做的就是对每个参数的值进行编码,因为它可能来自用户输入,使用的字符是未知的。
我开发了一个用于此目的的库: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上查看