ChatGPT解决这个技术问题 Extra ChatGPT

Java中的HTTP URL地址编码

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

吹毛求疵:根据定义包含空格字符的字符串不是 URI。因此,您正在寻找的是实现 Section 2.1 of RFC 3986 中定义的 URI 转义的代码。
这种行为是完全正确的。 URL 编码是将某些内容转换为可以安全地作为 URL 参数传递的字符串,并且根本不会被解释为 URL。而您希望它只转换 URL 的一小部分。

R
River

java.net.URI 类可以提供帮助;在您找到的 URL 文档中

请注意,URI 类在某些情况下会执行其组件字段的转义。管理 URL 编码和解码的推荐方法是使用 URI

使用具有多个参数的构造函数之一,例如:

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 字符的字符串:

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

请注意,这里提到的 URI 类来自 "org.apache.commons.httpclient.URI" 而不是 "java.net" ,"java.net" 不接受非法字符,除非你会使用从其组件构建 URL 的构造函数,就像下面的 Matt 评论中提到的方式
@Mohamed:我提到并用于测试的类实际上是 java.net.URI:它运行良好(Java 1.6)。如果它不是标准的 Java 类名并且链接指向 java.net.URI 的文档,我会提到完全限定的类名。而且,根据 Sudhakar 的评论,它在不包括任何“公共库”的情况下解决了问题!
URI uri = new URI("http", "search.barnesandnoble.com", "/booksearch/é",null);不使用此示例进行正确转义?这应该用 % escapes 转义
@fatih - 这是正确的,谢谢!通常这不应该是一个问题,但有一个简单的解决方案 - 几乎和我之前写的一样。见第二次编辑。
@Carlos Thx 进行编辑。现在它确实转义但不正确转义。它应该为路径参数的 char 的 HEX 值添加一个 %,这意味着应该将 é char 转换为 %e9
L
Lii

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

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

没错,URI构造函数已经对查询字符串进行了编码,根据文档docs.oracle.com/javase/1.4.2/docs/api/java/net/…,java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String )
@Draemon 答案是正确的,但以不常见的方式使用查询字符串;更正常的示例可能是 query = URLEncoder.encode(key) + "=" + URLEncoder.encode(value)。文档只是说“引用了任何不是合法 URI 字符的字符”。
我同意马特的观点。如果您在浏览器中键入此 URL:“google.com/help/me/book name+me/?MY CRZY QUERY!+&+ :)”,它会自动对空格进行编码,但“&”用作查询值分隔符,“+”丢失。
不幸的是,这个答案也是错误的,因为它对事物进行了双重编码。使用多参数 URI 构造函数,如果路径中有斜杠,或者查询参数或值中有“&”或“=”,则要么无法对它们进行编码,要么对它们进行双重编码。
C
Craig B

我将在这里添加一个针对 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 字符串并使其工作,而无需自己掌握任何特殊知识。


不错的方法,但我想指出,此代码不会阻止 双重编码,例如 %20 被编码为 %2520。 Scott's answer 不受此影响。
或者,如果您只想进行路径引用: new URI(null, null, "/path with spaces", null, null).toString()
@Stallman如果您的文件名包含#,则URL类会将其放入“ref”(相当于URI类中的“fragment”)。您可以检测 URL.getRef() 是否返回可能被视为路径一部分的内容,并将 URL.getPath() + "#" + URL.getRef() 作为“路径”参数传递,并将 null 作为“片段”传递" URI 类 7 参数构造函数的参数。默认情况下,# 之后的字符串被视为引用(或锚点)。
很好的答案,我有简单的网址,它对我有用。虽然我不认为它非常特定于android。我使用了 java.net.URIjava.net.URL,这个答案运行良好。我什至可以对此进行单元测试。
f
fmucar

我开发的一个解决方案比任何其他解决方案都更稳定:

public class URLParamEncoder {

    public static String encode(String input) {
        StringBuilder resultStr = new StringBuilder();
        for (char ch : input.toCharArray()) {
            if (isUnsafe(ch)) {
                resultStr.append('%');
                resultStr.append(toHex(ch / 16));
                resultStr.append(toHex(ch % 16));
            } else {
                resultStr.append(ch);
            }
        }
        return resultStr.toString();
    }

    private static char toHex(int ch) {
        return (char) (ch < 10 ? '0' + ch : 'A' + ch - 10);
    }

    private static boolean isUnsafe(char ch) {
        if (ch > 128 || ch < 0)
            return true;
        return " %$&+,/:;=?@<>#%".indexOf(ch) >= 0;
    }

}

这还需要您将 url 分成几部分。计算机无法知道要对 url 的哪一部分进行编码。见我上面的编辑
@fmucar 感谢那段代码!应该注意的是,这不是 UTF-8。要获得 UTF-8,只需使用 String utf8Input = new String(Charset.forName("UTF-8").encode(input).array()); 预处理输入(取自 here
该解决方案实际上还将“http://”部分编码为“http%3A%2F%2F”,这是最初的问题试图避免的。
您只传递您需要编码的内容,而不是整个 URL。没有办法传递一个完整的 URL 字符串并期望正确的编码。在所有情况下,您都需要将 url 分解为其逻辑部分。
我对这个答案有疑问,因为它不会将不安全的字符编码为 UTF-8 .. 不过可能取决于对等应用程序。
S
Scott Izu

如果你有一个 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;
    }
}

当您将字符串作为“google.co.in/search?q=123%!123”传递时,URLDecoder.decode(string, "UTF-8") 失败并出现 IllegalArgumentException。这是一个有效的 URL。我猜当 % 用作数据而不是编码字符时,此 API 不起作用。
S
SW4

是的,URL 编码将对该字符串进行编码,以便将其在 url 中正确传递到最终目的地。例如,您不能拥有 http://stackoverflow.com?url=http://yyy.com。 UrlEncoding 参数将修复该参数值。

所以我有两个选择给你:

您是否有权访问与域分开的路径?如果是这样,您可以简单地对路径进行 UrlEncode。但是,如果不是这种情况,那么选项 2 可能适合您。获取 commons-httpclient-3.1。这有一个类 URIUtil: System.out.println(URIUtil.encodePath("http://example.com/x y", "ISO-8859-1"));

这将准确地输出您要查找的内容,因为它只会对 URI 的路径部分进行编码。

仅供参考,您需要 commons-codec 和 commons-logging 才能使此方法在运行时工作。


旁注 apache commons 显然停止在 4.x 分支中维护 URIUtil,建议您改用 JDK 的 URI 类。只是意味着您必须自己分解字符串。
2)正是这里也建议stackoverflow.com/questions/5330104/…我也使用了URIUtil解决方案
C
Cuga

如果有人不想在他们的项目中添加依赖项,这些功能可能会有所帮助。

我们将 URL 的“路径”部分传递到此处。您可能不想将完整的 URL 作为参数传递(查询字符串需要不同的转义等)。

/**
 * Percent-encodes a string so it's suitable for use in a URL Path (not a query string / form encode, which uses + for spaces, etc)
 */
public static String percentEncode(String encodeMe) {
    if (encodeMe == null) {
        return "";
    }
    String encoded = encodeMe.replace("%", "%25");
    encoded = encoded.replace(" ", "%20");
    encoded = encoded.replace("!", "%21");
    encoded = encoded.replace("#", "%23");
    encoded = encoded.replace("$", "%24");
    encoded = encoded.replace("&", "%26");
    encoded = encoded.replace("'", "%27");
    encoded = encoded.replace("(", "%28");
    encoded = encoded.replace(")", "%29");
    encoded = encoded.replace("*", "%2A");
    encoded = encoded.replace("+", "%2B");
    encoded = encoded.replace(",", "%2C");
    encoded = encoded.replace("/", "%2F");
    encoded = encoded.replace(":", "%3A");
    encoded = encoded.replace(";", "%3B");
    encoded = encoded.replace("=", "%3D");
    encoded = encoded.replace("?", "%3F");
    encoded = encoded.replace("@", "%40");
    encoded = encoded.replace("[", "%5B");
    encoded = encoded.replace("]", "%5D");
    return encoded;
}

/**
 * Percent-decodes a string, such as used in a URL Path (not a query string / form encode, which uses + for spaces, etc)
 */
public static String percentDecode(String encodeMe) {
    if (encodeMe == null) {
        return "";
    }
    String decoded = encodeMe.replace("%21", "!");
    decoded = decoded.replace("%20", " ");
    decoded = decoded.replace("%23", "#");
    decoded = decoded.replace("%24", "$");
    decoded = decoded.replace("%26", "&");
    decoded = decoded.replace("%27", "'");
    decoded = decoded.replace("%28", "(");
    decoded = decoded.replace("%29", ")");
    decoded = decoded.replace("%2A", "*");
    decoded = decoded.replace("%2B", "+");
    decoded = decoded.replace("%2C", ",");
    decoded = decoded.replace("%2F", "/");
    decoded = decoded.replace("%3A", ":");
    decoded = decoded.replace("%3B", ";");
    decoded = decoded.replace("%3D", "=");
    decoded = decoded.replace("%3F", "?");
    decoded = decoded.replace("%40", "@");
    decoded = decoded.replace("%5B", "[");
    decoded = decoded.replace("%5D", "]");
    decoded = decoded.replace("%25", "%");
    return decoded;
}

和测试:

@Test
public void testPercentEncode_Decode() {
    assertEquals("", percentDecode(percentEncode(null)));
    assertEquals("", percentDecode(percentEncode("")));

    assertEquals("!", percentDecode(percentEncode("!")));
    assertEquals("#", percentDecode(percentEncode("#")));
    assertEquals("$", percentDecode(percentEncode("$")));
    assertEquals("@", percentDecode(percentEncode("@")));
    assertEquals("&", percentDecode(percentEncode("&")));
    assertEquals("'", percentDecode(percentEncode("'")));
    assertEquals("(", percentDecode(percentEncode("(")));
    assertEquals(")", percentDecode(percentEncode(")")));
    assertEquals("*", percentDecode(percentEncode("*")));
    assertEquals("+", percentDecode(percentEncode("+")));
    assertEquals(",", percentDecode(percentEncode(",")));
    assertEquals("/", percentDecode(percentEncode("/")));
    assertEquals(":", percentDecode(percentEncode(":")));
    assertEquals(";", percentDecode(percentEncode(";")));

    assertEquals("=", percentDecode(percentEncode("=")));
    assertEquals("?", percentDecode(percentEncode("?")));
    assertEquals("@", percentDecode(percentEncode("@")));
    assertEquals("[", percentDecode(percentEncode("[")));
    assertEquals("]", percentDecode(percentEncode("]")));
    assertEquals(" ", percentDecode(percentEncode(" ")));

    // Get a little complex
    assertEquals("[]]", percentDecode(percentEncode("[]]")));
    assertEquals("a=d%*", percentDecode(percentEncode("a=d%*")));
    assertEquals(")  (", percentDecode(percentEncode(")  (")));
    assertEquals("%21%20%2A%20%27%20%28%20%25%20%29%20%3B%20%3A%20%40%20%26%20%3D%20%2B%20%24%20%2C%20%2F%20%3F%20%23%20%5B%20%5D%20%25",
                    percentEncode("! * ' ( % ) ; : @ & = + $ , / ? # [ ] %"));
    assertEquals("! * ' ( % ) ; : @ & = + $ , / ? # [ ] %", percentDecode(
                    "%21%20%2A%20%27%20%28%20%25%20%29%20%3B%20%3A%20%40%20%26%20%3D%20%2B%20%24%20%2C%20%2F%20%3F%20%23%20%5B%20%5D%20%25"));

    assertEquals("%23456", percentDecode(percentEncode("%23456")));

}

谢谢你,但是我需要做什么来编码一个空间 - >根据你的例子使用 %20 代替?
更新为将空格占为 %20
t
takrl

不幸的是,org.apache.commons.httpclient.util.URIUtil 已被弃用,replacement org.apache.commons.codec.net.URLCodec 的编码适用于表单帖子,而不是实际的 URL。所以我必须编写我自己的函数,它只做一个组件(不适合具有?和 & 的整个查询字符串)

public static String encodeURLComponent(final String s)
{
  if (s == null)
  {
    return "";
  }

  final StringBuilder sb = new StringBuilder();

  try
  {
    for (int i = 0; i < s.length(); i++)
    {
      final char c = s.charAt(i);

      if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||
          ((c >= '0') && (c <= '9')) ||
          (c == '-') ||  (c == '.')  || (c == '_') || (c == '~'))
      {
        sb.append(c);
      }
      else
      {
        final byte[] bytes = ("" + c).getBytes("UTF-8");

        for (byte b : bytes)
        {
          sb.append('%');

          int upper = (((int) b) >> 4) & 0xf;
          sb.append(Integer.toHexString(upper).toUpperCase(Locale.US));

          int lower = ((int) b) & 0xf;
          sb.append(Integer.toHexString(lower).toUpperCase(Locale.US));
        }
      }
    }

    return sb.toString();
  }
  catch (UnsupportedEncodingException uee)
  {
    throw new RuntimeException("UTF-8 unsupported!?", uee);
  }
}

来吧,必须有一个图书馆可以做到这一点。
B
Brandon Yarbrough

正如您不幸发现的那样,URLEncoding 可以很好地编码 HTTP URL。您传入的字符串“http://search.barnesandnoble.com/booksearch/first book.pdf”已正确且完整地编码为 URL 编码形式。您可以将返回的整个 gobbledigook 长字符串作为 URL 中的参数传递,并且可以将其解码回您传入的字符串。

听起来您想做一些不同于将整个 URL 作为参数传递的事情。根据我收集的信息,您正在尝试创建一个类似于“http://search.barnesandnoble.com/booksearch/whateverTheUserPassesIn”的搜索 URL。您唯一需要编码的是“whateverTheUserPassesIn”位,所以也许您需要做的就是这样的:

String url = "http://search.barnesandnoble.com/booksearch/" + 
       URLEncoder.encode(userInput,"UTF-8");

那应该会产生对您更有效的东西。


这将用“+”替换 userInput 中的空格。发帖人需要将它们替换为“%20”。
@vocaro:这是一个很好的观点。 URLEncoder 转义就像参数是查询参数,而不像 URL 的其余部分。
E
Emilien Brigand

我阅读了以前的答案来编写自己的方法,因为使用以前的答案的解决方案无法正常工作,这对我来说看起来不错,但是如果您能找到不适用于此的 URL,请告诉我。

public static URL convertToURLEscapingIllegalCharacters(String toEscape) throws MalformedURLException, URISyntaxException {
            URL url = new URL(toEscape);
            URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
            //if a % is included in the toEscape string, it will be re-encoded to %25 and we don't want re-encoding, just encoding
            return new URL(uri.toString().replace("%25", "%"));
}

example.com?q=plus+plus noplus”加号未编码,可能会被视为空格字符
s
simonox

如果您的 URL 中有编码的“/” (%2F),仍然存在问题。

RFC 3986 - 第 2.2 节说:“如果 URI 组件的数据与保留字符作为分隔符的用途发生冲突,则冲突数据必须在 URI 形成之前进行百分比编码。” (RFC 3986 - 第 2.2 节)

但是Tomcat有一个问题:

http://tomcat.apache.org/security-6.html - 在 Apache Tomcat 6.0.10 中修复重要:目录遍历 CVE-2007-0450 Tomcat 允许 '\'、'%2F' 和 '%5C' [.. .] .以下 Java 系统属性已添加到 Tomcat,以提供对 URL 中路径分隔符处理的额外控制(两个选项默认为 false): org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true|false org.apache .catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: true|false 由于无法保证所有 URL 都由 Tomcat 处理,就像它们在代理服务器中一样,因此应该始终保护 Tomcat,就好像没有使用限制上下文访问的代理一样。影响:6.0.0-6.0.9

因此,如果您有一个带有 %2F 字符的 URL,Tomcat 会返回:“400 Invalid URI: noSlash”

您可以在 Tomcat 启动脚本中切换错误修复:

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%   -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 

n
negora

我同意马特的观点。确实,我从来没有在教程中看到过很好的解释,但是一个问题是如何对 URL 路径进行编码,而一个非常不同的问题是如何对附加到 URL 的参数进行编码(查询部分,在 "? “ 象征)。它们使用相似的编码,但不一样。

专门用于空白字符的编码。 URL 路径需要将其编码为 %20,而查询部分允许使用 %20 以及“+”号。最好的办法是我们自己使用 Web 浏览器针对我们的 Web 服务器对其进行测试。

对于这两种情况,我总是对 COMPONENT BY COMPONENT 进行编码,而不是对整个字符串进行编码。确实 URLEncoder 允许查询部分。对于路径部分,您可以使用类 URI,尽管在这种情况下它要求提供整个字符串,而不是单个组件。

无论如何,我相信避免这些问题的最好方法是使用个人非冲突设计。如何?例如,我绝不会使用 aZ、AZ、0-9 和 _ 以外的其他字符来命名目录或参数。这样,唯一需要对每个参数的值进行编码,因为它可能来自用户输入并且使用的字符是未知的。


使用问题中的 URL 的示例代码将是一件好事
m
micahli123

也许可以在 org.springframework.web.util 中尝试 UriUtils

UriUtils.encodeUri(input, "UTF-8")

T
To Kra

您还可以使用 GUAVA 和路径转义器:UrlEscapers.urlFragmentEscaper().escape(relativePath)


C
ChrisG65

我把上面的内容做了一些改动。我首先喜欢积极的逻辑,我认为 HashSet 可能比其他一些选项提供更好的性能,比如搜索字符串。虽然,我不确定自动装箱惩罚是否值得,但如果编译器针对 ASCII 字符进行优化,那么装箱成本会很低。

/***
 * Replaces any character not specifically unreserved to an equivalent 
 * percent sequence.
 * @param s
 * @return
 */
public static String encodeURIcomponent(String s)
{
    StringBuilder o = new StringBuilder();
    for (char ch : s.toCharArray()) {
        if (isSafe(ch)) {
            o.append(ch);
        }
        else {
            o.append('%');
            o.append(toHex(ch / 16));
            o.append(toHex(ch % 16));
        }
    }
    return o.toString();
}

private static char toHex(int ch)
{
    return (char)(ch < 10 ? '0' + ch : 'A' + ch - 10);
}

// https://tools.ietf.org/html/rfc3986#section-2.3
public static final HashSet<Character> UnreservedChars = new HashSet<Character>(Arrays.asList(
        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
        '0','1','2','3','4','5','6','7','8','9',
        '-','_','.','~'));
public static boolean isSafe(char ch)
{
    return UnreservedChars.contains(ch);
}

M
Martin Dimitrov

除了 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();

j
jschnasse

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

0. Test if URL is already encoded

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


N
Nick Allen

如果您使用的是 spring,您可以尝试 org.springframework.web.util.UriUtils#encodePath


U
Uriah Carpenter

我创建了一个新项目来帮助构建 HTTP URL。该库将自动对路径段和查询参数进行 URL 编码。

您可以在 https://github.com/Widen/urlbuilder 查看源代码并下载二进制文件

此问题中的示例 URL:

new UrlBuilder("search.barnesandnoble.com", "booksearch/first book.pdf").toString()

生产

http://search.barnesandnoble.com/booksearch/first%20book.pdf


R
Richard R

我有同样的问题。通过取消解决这个问题:

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

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


s
smola

我开发了一个用于此目的的库: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


我不确定为什么这个答案被如此低估。这个库虽然占用空间有点大,但正是我需要的。
d
developer learn999

我用这个

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

添加此依赖项

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

这会转义 HTML 标记,但不会转义 URL
S
Salim Hamidi

您可以使用这样的功能。根据您的需要完成并修改它:

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


如果没有 URLCodec,这个答案是不完整的。
支持 .replace() 链接,它并不理想,但对于基本的临时用例来说已经足够了
M
MichaelICE

怎么样:

公共字符串 UrlEncode(字符串 in_){

String retVal = "";

try {
    retVal = URLEncoder.encode(in_, "UTF8");
} catch (UnsupportedEncodingException ex) {
    Log.get().exception(Log.Level.Error, "urlEncode ", ex);
}

return retVal;

}


URLEncoder 不能用于转义有效的 URL 字符。仅对表单进行编码。