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


当前回答

我用这个

org.apache.commons.text.StringEscapeUtils.escapeHtml4("my text % & < >");

添加这个依赖项

 <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-text</artifactId>
        <version>1.8</version>
    </dependency>

其他回答

使用以下标准Java解决方案(通过Web平台测试提供的大约100个测试用例):

0. 测试URL是否已经编码。

1. 将URL拆分为结构部分。使用java.net.URL。

2. 正确编码每个结构部分!

3.使用IDN.toASCII(putDomainNameHere)对主机名进行Punycode编码!

4. 使用java.net.URI.toASCIIString()进行百分比编码,NFC编码的unicode -(更好的是NFKC!)

更多信息请访问:https://stackoverflow.com/a/49796882/1485527

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

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

/**
     * 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

请注意,上面的大部分答案都是不正确的。

URLEncoder类,不管它的名字,不是这里需要的。不幸的是,Sun给这个类命名得如此烦人。URLEncoder用于作为参数传递数据,而不是用于对URL本身进行编码。

换句话说,“http://search.barnesandnoble.com/booksearch/first book.pdf”是URL。参数可以是,例如,“http://search.barnesandnoble.com/booksearch/first book.pdf?parameter1=this&param2=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