Codificando parâmetros de consulta de URL em Java


108

Como codificar parâmetros de consulta para ir em uma url em Java? Eu sei, isso parece uma pergunta óbvia e já feita.

Existem duas sutilezas das quais não tenho certeza:

  1. Os espaços devem ser codificados no url como "+" ou como "% 20"? No Chrome, se eu digitar "http://google.com/foo=?bar me", o Chrome muda para ser codificado com% 20
  2. É necessário / correto codificar dois pontos ":" como% 3B? Chrome não.

Notas:

  • java.net.URLEncoder.encodenão parece funcionar, parece que a codificação de dados deve ser enviada do formulário. Por exemplo, ele codifica o espaço em +vez de %20e codifica dois pontos, o que não é necessário.
  • java.net.URI não codifica parâmetros de consulta


2
a estrutura da parte da consulta depende do servidor, embora a maioria espere application/x-www-form-urlencodedpares de chave / valor. Veja aqui para mais informações: ilegalargumentexception.blogspot.com/2009/12/…
— McDowell

Respostas:


127

java.net.URLEncoder.encode(String s, String encoding)pode ajudar também. Ele segue a codificação do formulário HTML application/x-www-form-urlencoded.

URLEncoder.encode(query, "UTF-8");

Por outro lado, a codificação Porcentagem (também conhecida como codificação de URL ) codifica o espaço com %20. Dois pontos é um caractere reservado, então :continuará sendo dois pontos após a codificação.


3
Eu mencionei que não acho que isso faça a codificação de url, em vez disso, codifica os dados a serem enviados por meio de um formulário. comentários?
— Alex Black

Isso porque URLEncoderestá em conformidade com o application/x-www-form-urlencodedformato MIME (que é uma codificação de formulário HTML válida). Presumo que não seja isso que você está procurando.
— Buhake Sindi

6
Acabei usando URLEncoder.encode e substituindo "+" por "% 20"
— Alex Black

2
Ele codifica barras como "% 2F", não deveria deixar as barras de URL como estão?
— golimar

6
@golimar Não, não deveria. Você deve fornecer apenas o valor do parâmetro e não a URL inteira. Considere o exemplo http://example.com/?url=http://example.com/?q=c&sort=name. Deve codificar &sort=nameou não? Não há como distinguir o valor do URL. Essa é a razão exata pela qual você precisa da codificação de valor em primeiro lugar.
— Pijusn

15

EDIT: URIUtilnão está mais disponível em versões mais recentes, melhor resposta em Java - encode URL ou pelo Sr. Sindi neste tópico.


URIUtildo Apache httpclient é realmente útil, embora existam algumas alternativas

URIUtil.encodeQuery(url);

Por exemplo, ele codifica o espaço como "+" em vez de "% 20"

Ambos são perfeitamente válidos no contexto certo . Embora se você realmente preferisse, você poderia emitir uma substituição de string.


Eu tenho que concordar. Use o HttpClient, você será muito mais feliz.
— DaShaun

Parece promissor, conseguiu um link por acaso? Estou pesquisando, mas encontrando muitos.
— Alex Black

1
Este método não parece estar presente no HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
— Alex Black

@Alex, hmm que chato, sempre usei essa rotina com bons resultados. Uma ideia é pegar o código-fonte da versão 3, já que agora eles obviamente não queriam mais mantê-lo.
— Johan Sjöberg,

1
URIUtil.encodeWithinQueryé o que você usaria para codificar um parâmetro de consulta individual, que é o que a pergunta original parecia estar perguntando.
— Jesse Glick

13

Infelizmente, URLEncoder.encode () não produz codificação de porcentagem válida (conforme especificado em RFC 3986 ).

URLEncoder.encode () codifica tudo perfeitamente, exceto o espaço é codificado para "+". Todos os codificadores URI Java que consegui encontrar expõem apenas métodos públicos para codificar a consulta, o fragmento, as partes do caminho, etc. - mas não expõe a codificação "bruta". Isso é lamentável, pois o fragmento e a consulta podem codificar o espaço para +, então não queremos usá-los. O caminho está codificado corretamente, mas é "normalizado" primeiro, portanto também não podemos usá-lo para codificação "genérica".

Melhor solução que eu poderia apresentar:

return URLEncoder.encode(raw, "UTF-8").replaceAll("\\+", "%20");

E se replaceAll() for muito lento para você, acho que a alternativa é rolar seu próprio codificador ...

EDITAR: Eu coloquei este código aqui primeiro, que não codifica "?", "&", "=" Corretamente:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);

+é uma codificação perfeitamente válida de um espaço.
— Lawrence Dol

@LawrenceDol é verdade, mas às vezes +pode ser interpretado incorretamente - dê uma olhada em C # blogs.msdn.microsoft.com/yangxind/2006/11/08/…
— Lu55

Este. Eu comparei várias alternativas com a encodeURIComponentsaída do método Javascript , e esta foi a única correspondência exata para as que tentei (consultas com espaços, caracteres especiais turcos e alemães).
— Utku Özdemir

8

Não é necessário codificar dois-pontos como% 3B na consulta, embora isso não seja ilegal.

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Também parece que apenas espaços codificados por cento são válidos, pois duvido que o espaço seja um ALFA ou um DÍGITO

consulte a especificação URI para obter mais detalhes.


Mas fazer isso pode mudar o significado do URI, uma vez que a interpretação da string de consulta depende do servidor. Se você estiver produzindo uma application/x-www-form-urlencodedstring de consulta, qualquer uma das opções está correta. Se você estiver corrigindo um URL que o usuário digitou / colou, :deve ser deixado sozinho.
— tc.

@tc. Você está certo, se dois pontos estão sendo usados ​​como um delimitador geral (página 12 da RFC); no entanto, se não estiver sendo usado como um delimitador geral, ambas as codificações devem resolver de forma idêntica.
— Edwin Buck

Você também deve ter cuidado, pois os URLs não são realmente um subconjunto do URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
— Adam Gent

5

O URLEncoder Java integrado está fazendo o que deveria e você deve usá-lo.

A "+" ou "% 20" são ambos os substitutos válidos para um caractere de espaço em uma URL. Qualquer um vai funcionar.

Um ":" deve ser codificado, pois é um caractere separador. ou seja, http: // foo ou ftp: // bar . O fato de que um navegador específico pode manipulá-lo quando não está codificado não o torna correto. Você deve codificá-los.

Como uma questão de boa prática, certifique-se de usar o método que usa um parâmetro de codificação de caracteres. UTF-8 é geralmente usado lá, mas você deve fornecê-lo explicitamente.

URLEncoder.encode(yourUrl, "UTF-8");

5
+é apenas uma representação do espaço em application/x-www-form-urlencoded; não é garantido que funcione mesmo quando restrito a HTTP. Da mesma forma, :é válido em uma string de consulta e não deve ser convertido para %3B; um servidor pode escolher interpretá-los de maneira diferente.
— tc.

1
este método também codificam barras url integrais e outros personagens que fazem parte por exemplo, http://a http%3A%2F%2Fque não é correto
— Para Kra

2
@ToKra você não deve codificar a http://parte. O método é para parâmetros de consulta e dados de formulário codificados. Se, no entanto, você quiser passar o URL de outro site como um parâmetro de consulta, ENTÃO você deseja codificá-lo para evitar confundir o analisador de URL.
— Beldaz

@tc Minha leitura de w3.org/TR/html4/interact/forms.html#h-17.13.3.3 é que todos os dados do formulário GET são codificados como application/x-www-form-urlencodedtipo de conteúdo. Isso não significa que deve funcionar para HTTP?
— beldaz

0

se você tem apenas problema de espaço na url. Eu usei o código abaixo e funcionou bem

String url;
URL myUrl = new URL(url.replace(" ","%20"));

exemplo: url é

www.xyz.com?para=hello senhor

então a saída de muUrl é

www.xyz.com?para=hello%20sir


0
String param="2019-07-18 19:29:37";
param="%27"+param.trim().replace(" ", "%20")+"%27";

Observei no caso de Datetime (Timestamp) URLEncoder.encode(param,"UTF-8")não funcionar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.