web-dev-qa-db-ja.com

クエリ文字列パラメータのJava URLエンコード

URLがあるとしましょう

http://example.com/query?q=

そして私はユーザーによって入力されたようなクエリを持っています:

ランダムワード£500 bank $

結果が正しくエンコードされたURLになるようにします。

http://example.com/query?q=random%20Word%20%A3500%20bank%20%24

これを達成するための最良の方法は何ですか?私はURLEncoderを作成してURI/URLオブジェクトを作成しようとしましたが、どれも正しい結果を出しませんでした。

639
user1277546

URLEncoder は行くべき道であるべきです。クエリ文字列パラメータの区切り文字&やパラメータ名ではなく、URL全体ではなく、個々のクエリ文字列パラメータの名前や値をエンコードのみするだけで構いません。値区切り文字=

String q = "random Word £500 bank $";
String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");

クエリパラメータ内のスペースは+ではなく%20で表されることに注意してください。これは合法的に有効です。 %20は通常、クエリ文字列(?の後の部分)ではなく、URI自体(URI-クエリ文字列の区切り文字の?の前の部分)のスペースを表すために使用されます。

2つのencode()メソッドがあることにも注意してください。文字セット引数のないものとあります。 charset引数のないものは推奨されません。絶対に使用せず、常にcharset引数を指定してください。 javadoc は、 RFC 3986 および W 3 C で規定されているように、UTF-8エンコーディングの使用を明示的に推奨します。

他のすべての文字は安全ではなく、まず何らかの符号化方式を使用して1つ以上のバイトに変換されます。その後、各バイトは3文字の文字列 "%xy"で表されます。ここで、xyはバイトの2桁の16進表現です。 推奨されるエンコード方式はUTF-8です。ただし、互換性の理由から、エンコーディングが指定されていない場合は、プラットフォームのデフォルトのエンコーディングが使用されます。

また見なさい:

1069
BalusC

URLEncoderは使いません。誤った名前(URLEncoderはURLとは無関係)であることに加えて、非効率的です(Builderの代わりにStringBufferを使用し、低速の他のいくつかのことを行います)。

代わりに、 URIBuilder または Springのorg.springframework.web.util.UriUtils.encodeQueryまたはCommons ApacheのHttpClient を使用します。その理由は、パラメータ値とは異なる方法でクエリパラメータ名(つまりBalusCの答えq)をエスケープする必要があるということです。

上記の唯一のマイナス面は(私が痛いほど気付いたことですが)、 URLはURIの真のサブセットではないことです

サンプルコード

import org.Apache.http.client.utils.URIBuilder;

URIBuilder ub = new URIBuilder("http://example.com/query");
ub.addParameter("q", "random Word £500 bank \$");
String url = ub.toString();

// Result: http://example.com/query?q=random+Word+%C2%A3500+bank+%24

他の回答にリンクしているだけなので、これをコミュニティウィキとしてマークしました。気軽に編集してください

150
Adam Gent

最初に次のようなURIを作成する必要があります。

    String urlStr = "http://www.example.com/CEREC® Materials & Accessories/IPS Empress® CAD.pdf"
    URL url= new URL(urlStr);
    URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());

それから、そのUriをASCII stringに変換します。

    urlStr=uri.toASCIIString();

これで、あなたのURL文字列は最初に完全にエンコードされ、次に単純なURLエンコードを行い、それからそれをASCII St​​ringに変換してUS-ASCIIの外側の文字が残っていないことを確認します。これはまさにブラウザの動作方法です。

89
M Abdul Sami

Guava 15では 一連の簡単なURLエスケープ が追加されました。

34

Apache Http Componentsライブラリはクエリパラメータの構築とエンコードのためのきちんとしたオプションを提供します -

HttpComponents 4.xでは - URLEncodedUtils を使用してください。

HttpClient 3.xの場合は、 - EncodingUtil を使用します。

6
Sashi

これは、URL文字列とパラメータのマップを、クエリパラメータを含む有効なエンコードされたURL文字列に変換するためにコードで使用できるメソッドです。

String addQueryStringToUrlString(String url, final Map<Object, Object> parameters) throws UnsupportedEncodingException {
    if (parameters == null) {
        return url;
    }

    for (Map.Entry<Object, Object> parameter : parameters.entrySet()) {

        final String encodedKey = URLEncoder.encode(parameter.getKey().toString(), "UTF-8");
        final String encodedValue = URLEncoder.encode(parameter.getValue().toString(), "UTF-8");

        if (!url.contains("?")) {
            url += "?" + encodedKey + "=" + encodedValue;
        } else {
            url += "&" + encodedKey + "=" + encodedValue;
        }
    }

    return url;
}
5
Pellet

次の標準的なJavaソリューションを使用してください( Web Plattform Tests で提供されるテストケースを約100回通過します)。

0。URLがすでにエンコードされているかどうかをテストします 。 '+'エンコードスペースを '%20'エンコードスペースに置き換えます。

1。URLを構造部分に分割します。それにはJava.net.URLを使用してください。

2。各構造部分を正しくエンコードしてください。

3.ホスト名を Punycode でエンコードするには、IDN.toASCII(putDomainNameHere)を使用します。

4。パーセントエンコード、NFCエンコードされたUnicodeへのJava.net.URI.toASCIIString()の使用 - (より良いのはNFKCでしょう!)詳細については、 このURLを正しくエンコードする方法 を参照してください。

URL url= new URL("http://example.com/query?q=random Word £500 bank $");
URI uri = new URI(url.getProtocol(), url.getUserInfo(), IDN.toASCII(url.getHost()), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
String correctEncodedURL=uri.toASCIIString(); 
System.out.println(correctEncodedURL);

版画

http://example.com/query?q=random%20Word%20%C2%A3500%20bank%20$

これはまた正しく働くいくつかの例です。

{
      "in" : "http://نامه‌ای.com/",
     "out" : "http://xn--mgba3gch31f.com/"
},{
     "in" : "http://www.example.com/‥/foo",
     "out" : "http://www.example.com/%E2%80%A5/foo"
},{
     "in" : "http://search.barnesandnoble.com/booksearch/first book.pdf", 
     "out" : "http://search.barnesandnoble.com/booksearch/first%20book.pdf"
}, {
     "in" : "http://example.com/query?q=random Word £500 bank $", 
     "out" : "http://example.com/query?q=random%20Word%20%C2%A3500%20bank%20$"
}
4
jschnasse

私の場合は、URL全体を渡して各パラメータの値だけをエンコードする必要があります。そのための共通のコードが見つからなかったので(!!)、この小さなメソッドを作成して仕事をしていました。

public static String encodeUrl(String url) throws Exception {
    if (url == null || !url.contains("?")) {
        return url;
    }

    List<String> list = new ArrayList<>();
    String rootUrl = url.split("\\?")[0] + "?";
    String paramsUrl = url.replace(rootUrl, "");
    List<String> paramsUrlList = Arrays.asList(paramsUrl.split("&"));
    for (String param : paramsUrlList) {
        if (param.contains("=")) {
            String key = param.split("=")[0];
            String value = param.replace(key + "=", "");
            list.add(key + "=" +  URLEncoder.encode(value, "UTF-8"));
        }
        else {
            list.add(param);
        }
    }

    return rootUrl + StringUtils.join(list, "&");
}

public static String decodeUrl(String url) throws Exception {
    return URLDecoder.decode(url, "UTF-8");
}

それはorg.Apache.commons.lang3.StringUtilsを使います

1
Laurent

Androidでは、このコードを使用します。

Uri myUI = Uri.parse ("http://example.com/query").buildUpon().appendQueryParameter("q","random Word A3500 bank 24").build();

UriAndroid.net.Uriです。

0