我的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表单编码的实用程序类”…还有别的办法吗?


当前回答

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");

这应该会产生一些对你更有效的东西。

其他回答

在此我将针对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字符串并让它工作,而不需要您自己对它有任何特殊的了解。

如果你的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 

你可以使用这样的函数。根据您的需要完成并修改:

/**
     * Encode URL (except :, /, ?, &, =, ... characters)
     * @param url to encode
     * @param encodingCharset url encoding charset
     * @return encoded URL
     * @throws UnsupportedEncodingException
     */
    public static String encodeUrl (String url, String encodingCharset) throws UnsupportedEncodingException{
            return new URLCodec().encode(url, encodingCharset).replace("%3A", ":").replace("%2F", "/").replace("%3F", "?").replace("%3D", "=").replace("%26", "&");
    }

使用示例:

String urlToEncode = ""http://www.growup.com/folder/intérieur-à_vendre?o=4";
Utils.encodeUrl (urlToEncode , "UTF-8")

结果是:http://www.growup.com/folder/int%C3%A9rieur-%C3%A0_vendre?o=4

我也有同样的问题。通过unsing解决了这个问题:

android.net.Uri.encode(urlString, ":/");

它对字符串进行编码,但跳过“:”和“/”。

如果你用的是弹簧,你可以试试 org.springframework.web.util.UriUtils # encodePath