Mengenkode parameter kueri URL di Java

108

Bagaimana cara seseorang menyandikan parameter kueri ke url di Java? Saya tahu, ini sepertinya pertanyaan yang sudah jelas dan sudah ditanyakan.

Ada dua kehalusan yang saya tidak yakin:

  1. Haruskah spasi dikodekan pada url sebagai "+" atau sebagai "% 20"? Di chrome jika saya mengetik "http://google.com/foo=?bar me" chrome mengubahnya menjadi dienkode dengan% 20
  2. Apakah perlu / benar untuk mengenkode titik dua ":" sebagai% 3B? Chrome tidak.

Catatan:

  • java.net.URLEncoder.encodetampaknya tidak berfungsi, tampaknya untuk penyandian data harus dikirimkan. Misalnya, ia menyandikan spasi sebagai +pengganti %20, dan menyandikan titik dua yang tidak diperlukan.
  • java.net.URI tidak menyandikan parameter kueri
Alex Black
sumber
Pertanyaan ini tampaknya berguna: stackoverflow.com/questions/444112/…
Alex Black
2
struktur bagian kueri bergantung pada server, meskipun sebagian besar mengharapkan application/x-www-form-urlencodedpasangan kunci / nilai. Lihat di sini untuk lebih lanjut: illegalargumentexception.blogspot.com/2009/12/…
McDowell

Jawaban:

127

java.net.URLEncoder.encode(String s, String encoding)bisa membantu juga. Ini mengikuti pengkodean formulir HTML application/x-www-form-urlencoded.

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

Di sisi lain, Percent-encoding (juga dikenal sebagai URL encoding ) mengkodekan spasi dengan %20. Titik dua adalah karakter yang dicadangkan, jadi :akan tetap menjadi titik dua, setelah pengkodean.

Buhake Sindi
sumber
3
Saya sebutkan bahwa saya tidak berpikir itu melakukan pengkodean url, melainkan menyandikan data untuk dikirimkan melalui formulir. komentar?
Alex Black
Itu karena URLEncodertelah sesuai dengan application/x-www-form-urlencodedformat MIME (yang merupakan pengkodean formulir HTML yang valid). Saya berasumsi bukan itu yang Anda cari.
Buhake Sindi
6
Saya akhirnya menggunakan URLEncoder.encode dan mengganti "+" dengan "% 20"
Alex Black
2
Ini mengkodekan garis miring ke "% 2F", bukankah seharusnya garis miring URL dibiarkan begitu saja?
golimar
6
@golimar Tidak, seharusnya tidak. Anda seharusnya memberikan nilai parameter saja dan bukan keseluruhan URL. Perhatikan contoh http://example.com/?url=http://example.com/?q=c&sort=name. Haruskah itu menyandikan &sort=nameatau tidak? Tidak ada cara untuk membedakan nilai dari URL. Itulah alasan pasti mengapa Anda memerlukan pengkodean nilai sejak awal.
Pijusn
15

EDIT: URIUtiltidak lagi tersedia dalam versi yang lebih baru, jawaban yang lebih baik di Java - encode URL atau oleh Mr. Sindi di utas ini.


URIUtilApache httpclient sangat berguna, meskipun ada beberapa alternatif

URIUtil.encodeQuery(url);

Misalnya, ini mengkodekan spasi sebagai "+" bukan "% 20"

Keduanya benar - benar valid dalam konteks yang benar . Meskipun jika Anda benar-benar lebih suka, Anda bisa mengeluarkan string replace.

Johan Sjöberg
sumber
Saya harus setuju. Gunakan HttpClient, Anda akan jauh lebih bahagia.
DaShaun
Tampak menjanjikan, mendapat tautan secara kebetulan? Saya googling tapi menemukan banyak.
Alex Black
1
Metode ini sepertinya tidak ada di HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Alex Black
@Alex, hmm menyebalkan, saya selalu menggunakan rutinitas itu dengan hasil yang bagus. Salah satu idenya adalah mengambil kode sumber dari rilis 3 karena mereka sekarang jelas tidak ingin mempertahankannya lagi.
Johan Sjöberg
1
URIUtil.encodeWithinQueryadalah apa yang akan Anda gunakan untuk menyandikan parameter kueri individual, yang sepertinya ditanyakan oleh pertanyaan asli.
Jesse Glick
13

Sayangnya, URLEncoder.encode () tidak menghasilkan encoding persen yang valid (seperti yang ditentukan di RFC 3986 ).

URLEncoder.encode () mengkodekan semuanya dengan baik, kecuali spasi dikodekan menjadi "+". Semua pembuat enkode URI Java yang dapat saya temukan hanya mengekspos metode publik untuk menyandikan kueri, fragmen, bagian jalur, dll. - tetapi jangan mengekspos pengkodean "mentah". Ini sangat disayangkan karena fragmen dan kueri diizinkan untuk menyandikan spasi menjadi +, jadi kami tidak ingin menggunakannya. Jalur dikodekan dengan benar tetapi "dinormalisasi" terlebih dahulu sehingga kami juga tidak dapat menggunakannya untuk pengkodean 'umum'.

Solusi terbaik yang bisa saya dapatkan:

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

Jika replaceAll()terlalu lambat untuk Anda, saya kira alternatifnya adalah memutar pembuat enkode Anda sendiri ...

EDIT: Saya memiliki kode ini terlebih dahulu yang tidak menyandikan "?", "&", "=" Dengan benar:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);
Kosta
sumber
+adalah pengkodean spasi yang valid.
Lawrence Dol
@LawrenceDol itu benar tapi kadang-kadang +dapat ditafsirkan secara keliru - lihatlah C # blogs.msdn.microsoft.com/yangxind/2006/11/08/...
Lu55
Ini. Saya membandingkan berbagai alternatif terhadap encodeURIComponentkeluaran metode Javascript , dan ini adalah satu-satunya kecocokan tepat untuk yang saya coba (kueri dengan spasi, karakter khusus Turki dan Jerman).
Utku Özdemir
8

Tidak perlu mengenkode titik dua sebagai% 3B dalam kueri, meskipun hal itu tidak ilegal.

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

Tampaknya juga hanya spasi dengan enkode persen yang valid, karena saya ragu bahwa spasi tersebut adalah ALPHA atau DIGIT

lihat spesifikasi URI untuk detail selengkapnya.

Edwin Buck
sumber
Namun melakukan hal itu dapat mengubah arti URI, karena interpretasi string kueri tergantung pada server. Jika Anda menghasilkan application/x-www-form-urlencodedstring kueri, keduanya baik-baik saja. Jika Anda memperbaiki URL yang diketik / ditempel pengguna, :sebaiknya dibiarkan saja.
tc.
@. Anda benar, jika titik dua digunakan sebagai pembatas umum (halaman 12 RFC); namun, jika tidak digunakan sebagai pembatas umum, kedua pengkodean harus diselesaikan secara identik.
Edwin Buck
Anda juga harus berhati-hati karena URL sebenarnya bukan bagian dari URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent
5

URLEncoder Java bawaan melakukan apa yang seharusnya, dan Anda harus menggunakannya.

"+" Atau "% 20" keduanya merupakan pengganti yang valid untuk karakter spasi di URL. Salah satunya akan berhasil.

A ":" harus dienkode, karena ini adalah karakter pemisah. yaitu http: // foo atau ftp: // bar . Fakta bahwa browser tertentu dapat menanganinya saat tidak dikodekan tidak membuatnya benar. Anda harus menyandikannya.

Sebagai praktik yang baik, pastikan untuk menggunakan metode yang menggunakan parameter encoding karakter. UTF-8 umumnya digunakan di sana, tetapi Anda harus menyediakannya secara eksplisit.

URLEncoder.encode(yourUrl, "UTF-8");
rfeak
sumber
5
+hanya merupakan representasi ruang dalam application/x-www-form-urlencoded; itu tidak dijamin akan berfungsi bahkan ketika dibatasi untuk HTTP. Demikian pula, :valid dalam string kueri dan tidak boleh diubah menjadi %3B; server dapat memilih untuk menafsirkannya secara berbeda.
tc.
1
metode ini juga mengkodekan garis miring url utuh dan karakter lain yang merupakan bagian misalnya http://untuk http%3A%2F%2Fyang tidak benar
Untuk Kra
2
@ToKra Anda tidak seharusnya menyandikan http://bagian tersebut. Metode ini untuk parameter kueri dan data formulir yang dikodekan. Namun, jika Anda ingin meneruskan URL situs web lain sebagai parameter kueri, MAKA Anda ingin menyandikannya untuk menghindari kesalahan pengurai URL.
beldaz
@tc Bacaan saya tentang w3.org/TR/html4/interact/forms.html#h-17.13.3.3 adalah bahwa semua data formulir GET dikodekan sebagai application/x-www-form-urlencodedtipe konten. Bukankah itu berarti harus berfungsi untuk HTTP?
beldaz
0

jika Anda hanya memiliki masalah ruang di url. Saya telah menggunakan kode di bawah ini dan berfungsi dengan baik

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

contoh: url adalah

www.xyz.com?para=hello pak

maka keluaran muUrl adalah

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

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

Saya mengamati dalam kasus Datetime (Timestamp) URLEncoder.encode(param,"UTF-8")tidak berfungsi.

ICL Sales EXIMON
sumber