2014-10-08 81 views
2

目前有final URL url = new URL(urlString);,但我遇到了不支持路徑中非ASCII的服務器。Java - 如何編碼非拉丁字符的URL路徑

使用Java(Android版),我需要從

http://acmeserver.com/download/agc/fcms/兒子去哪兒/兒子去哪兒.png 

編碼的URL

http://acmeserver.com/download/agc/fcms/%E5%84%BF%E5%AD%90%E5%8E%BB%E5%93%AA%E5%84%BF/%E5%84%BF%E5%AD%90%E5%8E%BB%E5%93%AA%E5%84%BF.png 

就像瀏覽器做。

我檢查URLEncoder.encode(s, "UTF-8");,但它也編碼/斜線

http%3A%2F%2acmeserver.com%2Fdownload%2Fagc%2Ffcms%2F%E5%84%BF%E5%AD%90%E5%8E%BB%E5%93%AA%E5%84%BF%2F%E5%84%BF%E5%AD%90%E5%8E%BB%E5%93%AA%E5%84%BF.png 

有沒有辦法做到這一點不只是解析字符串的方法獲取?

http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars

在URI屬性值

B.2.1非ASCII字符雖然URI是 不含非ASCII值(見[URI],第2.1節)作者 有時指定它們在屬性期望URI的值(即,在DTD中用%URI定義的 )。例如,下面的href的值 是非法的:

<A href="http://foo.org/Håkon">...</A>

我們建議用戶代理採取以下約定 在這種情況下,處理非ASCII字符:

  1. 表示每個字符UTF-8(參見[RFC2279])作爲一個或多個 字節。
  2. 使用URI轉義機制(即通過將每個字節轉換爲%HH,其中HH是字節值的十六進制標記 )轉義這些字節。

回答

4

您應該只編碼特殊字符並將它們解析在一起。如果你試圖編碼整個URI,那麼你會遇到問題。

棒有:

String query = URLEncoder.encode("apples oranges", "utf-8"); 
String url = "http://stackoverflow.com/search?q=" + query; 

看看這個great guide對URL編碼。

話雖這麼說,搜索的一點點暗示可能還有其他方法可以做到你想要什麼:

試試這個:

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

(你需要有這些空間編碼,所以你可以使用它的請求。)

這利用了幾個功能可供您在Android 類的優勢。首先,URL類可以將url分解爲其合適的 組件,因此不需要您執行任何字符串搜索/替換 的工作。其次,當您通過 組件構建URI而不是從單個字符串構建URI時,此方法利用了URI類 正確轉義組件的功能。

這種方法的美妙之處在於,您可以接受任何有效的url字符串 ,並且無需任何專門知識就可以使用它。

+0

好的,所以無論如何要創建一個URI對象。 – 2014-10-08 10:03:38

+0

是的。 URI是位置地址。如果您從未擁有過URI,那麼您的應用永遠不會知道發送/接收請求的位置。 – erad 2014-10-08 10:06:44

+0

我試圖作爲一個班輪'最終的URL url = new URI(urlString).toURL();'但它沒有編碼路徑。 – 2014-10-08 10:20:09

1

我做了如下,這是麻煩的

 //was: final URL url = new URL(urlString); 
     String asciiString; 
     try { 
      asciiString = new URL(urlString).toURI().toASCIIString(); 
     } catch (URISyntaxException e1) { 
      Log.e(TAG, "Error new URL(urlString).toURI().toASCIIString() " + urlString + " : " + e1); 
      return null; 
     } 
     Log.v(TAG, urlString+" -> "+ asciiString); 
     final URL url = new URL(asciiString); 

url

 connection = (HttpURLConnection) url.openConnection(); 
+0

只是好奇,但不是有點多餘?您正在接受一個字符串,將其轉換爲URL,並通過toURI()將其轉換回字符串,然後使用toASCIIString()對其進行編碼。 (所以你基本上是編碼它,只是在一行中。)public String toASCIIString() 以US-ASCII字符串形式返回此URI的內容。 如果此URI在其他類別中不包含任何字符,則此方法的調用將返回與調用toString方法相同的值。否則,此方法的工作原理就好像調用該方法,然後對結果進行編碼一樣。' – erad 2014-10-08 12:03:56

+0

是的,這是多餘的。 – 2014-10-09 02:10:13

1
final URL url = new URL(new URI(urlString).toASCIIString()); 

工作對我來說是以後使用。