HTTP URL एड्रेस जावा में एन्कोडिंग


366

मेरे जावा स्टैंडअलोन एप्लिकेशन को उपयोगकर्ता से एक 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 फॉर्म एन्कोडिंग के लिए उपयोगिता वर्ग" कहता है ... क्या ऐसा करने का कोई अन्य तरीका है?


1
यह भी देखें stackoverflow.com/questions/10786042/…
Raedwald

व्यवहार पूरी तरह से सही है। URL एनकोड कुछ को एक स्ट्रिंग में बदलना है जिसे सुरक्षित रूप से URL पैरामीटर के रूप में पारित किया जा सकता है, और एक URL के रूप में बिल्कुल भी व्याख्या नहीं की जाती है। जबकि आप चाहते हैं कि यह केवल URL के एक छोटे से हिस्से को रूपांतरित करें।
स्टीफन होल्ट

जवाबों:


303

Java.net.URI वर्ग मदद कर सकते हैं; आपके द्वारा खोजे गए URL के प्रलेखन में

ध्यान दें, यूआरआई वर्ग कुछ निश्चित परिस्थितियों में अपने घटक क्षेत्रों से भागने का प्रदर्शन करता है। 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 का एकल-तर्क निर्माता अवैध पात्रों से नहीं बचता)


केवल अवैध चरित्र उपरोक्त कोड से बच जाते हैं - यह गैर-एएससीआईआई पात्रों से नहीं बचता है (फ़ातिह की टिप्पणी देखें)। विधि केवल US-ASCII वर्ण के साथ एक स्ट्रिंग प्राप्त करने के लिए इस्तेमाल किया जा सकता:
toASCIIString

URI uri = new URI(
    "http", 
    "search.barnesandnoble.com", 
    "/booksearch/é",
    null);
String request = uri.toASCIIString();

जैसे क्वेरी वाले URL के लिए http://www.google.com/ig/api?weather=São Paulo, निर्माता के 5-पैरामीटर संस्करण का उपयोग करें:

URI uri = new URI(
        "http", 
        "www.google.com", 
        "/ig/api",
        "weather=São Paulo",
        null);
String request = uri.toASCIIString();

13
कृपया ध्यान दें, यहाँ उल्लिखित URI वर्ग "org.apache.commons.httpclient.URI" से है, "java.net" नहीं, "java.net", URI अवैध वर्णों को स्वीकार नहीं करता है, जब तक कि आप उपयोग नहीं करेंगे। निर्माणकर्ता जो इसके घटकों से URL
बनाते हैं

7
@ मोहम्मद: जिस वर्ग का मैंने उल्लेख किया और वास्तव में परीक्षण के लिए उपयोग किया हैjava.net.URI : वह पूरी तरह से काम करता है (जावा 1.6)। मैं पूरी तरह से योग्य वर्ग के नाम का उल्लेख करता हूं अगर यह मानक जावा एक नहीं था और प्रलेखन के लिए लिंक अंक java.net.URI। और, सुधाकर की टिप्पणी से, इसने बिना किसी "कॉमन्स लाइब्रेरी" को शामिल किए बिना समस्या को हल कर दिया!
user85421

1
URI uri = new URI ("http", "search.barnesandnoble.com", "/ booksearch / é", null); क्या इस नमूने के साथ भागने से सही नहीं होता है? यह% बच के साथ बच जाना चाहिए था
fmucar

@fatih - यह सही है, धन्यवाद! आम तौर पर यह एक समस्या नहीं होनी चाहिए, लेकिन एक सरल समाधान है - लगभग वैसा ही जैसा मैंने पहले लिखा था। 2 संपादित देखें।
user85421

@ संपादित करें Thx संपादन के लिए। अब यह बच निकलता है लेकिन भागने से नहीं। यह पथ परम के लिए चार वर्णों के HEX मान में एक% जोड़ना चाहिए जिसका अर्थ है कि char को% e9 में परिवर्तित किया जाना चाहिए
fmucar

91

कृपया चेतावनी दी जाए कि ऊपर दिए गए अधिकांश उत्तर INCORRECT हैं।

URLEncoderवर्ग, के बावजूद नाम है, नहीं क्या यहाँ होने की जरूरत है है। यह दुर्भाग्यपूर्ण है कि सूर्य ने इस वर्ग का नाम इतनी नाराज़गी से रखा। 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

2
यह सही है, 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)
मैडोक

8
@ उत्तर सही है लेकिन क्वेरी स्ट्रिंग का उपयोग असामान्य तरीके से करता है; एक अधिक सामान्य उदाहरण हो सकता है query = URLEncoder.encode(key) + "=" + URLEncoder.encode(value)। डॉक्स केवल इतना कहते हैं कि "कोई भी चरित्र जो कि कानूनी यूआरआई चरित्र नहीं है" उद्धृत किया गया है।
टीसी

1
मैं यहां मैट से सहमत हूं। यदि आप यह URL टाइप करते हैं: " google.com/help/me/book नाम + me /! मेरा CRZY QUERY! + & + :) :) ब्राउज़र में, यह स्वचालित रूप से रिक्त स्थान को एन्कोड करता है लेकिन" & "क्वेरी मान के रूप में उपयोग किया जाता है विभाजक और "+" खो जाते हैं।
अर्कॉट

80

मैं यहाँ एक सुझाव जोड़ने जा रहा हूँ जिसका उद्देश्य 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 में, मुझे उन स्थानों को इनकोडेड करने की आवश्यकता है ताकि मैं इसे अनुरोध के लिए उपयोग कर सकूं।

यह एंड्रॉइड कक्षाओं में आपके लिए उपलब्ध युगल सुविधाओं का लाभ उठाता है। सबसे पहले, URL वर्ग एक url को उसके उचित घटकों में तोड़ सकता है, इसलिए आपको कोई स्ट्रिंग खोज / प्रतिस्थापन कार्य करने की कोई आवश्यकता नहीं है। दूसरे, जब आप एक ही स्ट्रिंग के बजाय घटकों के माध्यम से URI का निर्माण करते हैं, तो यह दृष्टिकोण ठीक से बचने वाले घटकों के URI वर्ग सुविधा का लाभ उठाता है।

इस दृष्टिकोण की सुंदरता यह है कि आप किसी भी मान्य यूआरएल स्ट्रिंग को ले सकते हैं और इसे स्वयं के किसी विशेष ज्ञान की आवश्यकता के बिना काम कर सकते हैं।


3
अच्छा तरीका है, लेकिन मैं यह बताना चाहूंगा कि यह कोड डबल एन्कोडिंग को नहीं रोकता है , जैसे% 20 को 2520% में एन्कोड किया गया। स्कॉट का जवाब इससे ग्रस्त नहीं है।
nattster

2
यह संभाल नहीं सकता #
अल्स्टन

या यदि आप केवल पथ उद्धरण करना चाहते हैं: नया URI (अशक्त, अशक्त, "/ रिक्त स्थान के साथ पथ", null, null) .toString ()
user1050755

1
@Stallman यदि आपकी फ़ाइल का नाम # है, तो URL वर्ग इसे "Ref" (URI वर्ग में "टुकड़े" के बराबर) में डाल देगा। आप यह पता लगा सकते हैं कि URL.getRef () कुछ देता है जिसे पथ के एक भाग के रूप में माना जा सकता है और URL.getPath () + "#" + URL.getRef () "पथ" पैरामीटर और "टुकड़े" के रूप में रिक्त करें "यूआरआई वर्ग 7 पैरामीटर कंस्ट्रक्टर का पैरामीटर। डिफ़ॉल्ट रूप से, # के बाद स्ट्रिंग को संदर्भ (या एंकर) के रूप में माना जाता है।
गौसेज '

49

एक समाधान जो मैंने विकसित किया है और किसी भी अन्य की तुलना में बहुत अधिक स्थिर है:

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;
    }

}

3
इसके लिए आपको url को टुकड़ों में तोड़ना होगा। कंप्यूटर के लिए यह जानने का कोई तरीका नहीं है कि url के किस भाग को एनकोड करना है। मेरा उपरोक्त संपादन देखें
fmucar

4
@fmucar कोड के उस टुकड़े के लिए धन्यवाद! यह ध्यान दिया जाना चाहिए कि यह UTF-8 नहीं है। UTF-8 प्राप्त करने के लिए इनपुट को पूर्व-प्रक्रिया से String utf8Input = new String(Charset.forName("UTF-8").encode(input).array());( यहाँ से लिया गया )
letmaik

1
यह समाधान वास्तव में "http: //" भाग को "http% 3A% 2F% 2F" में सांकेतिक शब्दों में बदलना होगा, जो कि प्रारंभिक प्रश्न से बचने की कोशिश की गई थी।
बेंजामिन पीटर

2
आप केवल वही भरें जो आपको एनकोड करने की आवश्यकता है, न कि पूरे URL को। एक पूरे URL स्ट्रिंग को पास करने और सही एन्कोडिंग की अपेक्षा करने का कोई तरीका नहीं है। सभी मामलों में, आपको url को उसके तार्किक टुकड़ों में तोड़ने की आवश्यकता है।
fmucar

2
मुझे इस उत्तर के साथ समस्या थी क्योंकि यह UTF-8 को असुरक्षित वर्णों को एनकोड नहीं करता है .. हालांकि सहकर्मी के आवेदन पर निर्भर हो सकता है।
तरनचैफ

36

यदि आपके पास एक URL है, तो आप इस विधि में url.toString () पास कर सकते हैं। पहले डिकोडिंग, डबल एन्कोडिंग से बचने के लिए (उदाहरण के लिए,% 20 में एक स्थान परिणाम एन्कोडिंग और% 25 में एक प्रतिशत हस्ताक्षर परिणाम एन्कोडिंग है, इसलिए डबल एन्कोडिंग% 2520 में एक स्थान को बदल देगा)। फिर, URL के सभी हिस्सों को जोड़ते हुए (जैसा कि आप क्वेरी पैरामीटर को नहीं छोड़ते हैं) URI का उपयोग करें।

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;
    }
}

1
जब आप स्ट्रिंग को " google.co.in/search?q=123% -123" के रूप में पास करते हैं, तो URLDecoder.decode (स्ट्रिंग, "UTF-8") एक अवैध त्रुटि के साथ विफल हो जाता है । यह एक मान्य URL है। मुझे लगता है कि जब यह एन्कोडिंग चरित्र के बजाय डेटा के रूप में उपयोग किया जाता है तो यह एपीआई काम नहीं करता है।
मीडियमऑन

26

हाँ URL एन्कोडिंग उस स्ट्रिंग को एन्कोड करने वाला है ताकि इसे url में अंतिम गंतव्य तक ठीक से पास किया जा सके। उदाहरण के लिए आप http://stackoverflow.com?url=http://yyy.com नहीं हो सकते थे । UrlEncoding पैरामीटर उस पैरामीटर मान को ठीक करेगा।

तो मेरे पास आपके लिए दो विकल्प हैं:

  1. क्या आपके पास डोमेन से अलग पथ तक पहुंच है? यदि ऐसा है तो आप बस मार्ग को UrlEncode करने में सक्षम हो सकते हैं। हालाँकि, अगर ऐसा नहीं है तो विकल्प 2 आपके लिए हो सकता है।

  2. कॉमन्स- httpclient-3.1 प्राप्त करें। इसका एक वर्ग URIUtil है:

    System.out.println (URIUtil.encodePath (" http://example.com/x y", "ISO-8859-1"));

यह ठीक उसी तरह आउटपुट करेगा जैसा आप देख रहे हैं, क्योंकि यह केवल यूआरआई के पथ भाग को एन्कोड करेगा।

FYI करें, आपको रन-टाइम पर काम करने के लिए इस विधि के लिए कॉमन्स-कोडेक और कॉमन्स-लॉगिंग की आवश्यकता होगी।


सिडेनोट अपाचे कॉमन्स ने 4.x शाखाओं में URIUtil को बनाए रखना बंद कर दिया है, जाहिर है कि आप JDK के URI वर्ग का उपयोग करने की सलाह देते हैं। बस इसका मतलब है कि आपको खुद ही स्ट्रिंग को तोड़ना होगा।
निकॉली

2) बिल्कुल यह भी सुझाव दिया गया है कि यहां stackoverflow.com/questions/5330104/… मैंने भी URIUtilसमाधान का उपयोग किया है
To Kra

11

नाइटपैकिंग: परिभाषा के अनुसार एक व्हाट्सएप चरित्र युक्त एक स्ट्रिंग एक यूआरआई नहीं है। तो आप जिस चीज की तलाश कर रहे हैं वह कोड है जो RFC 3986 की धारा 2.1 में परिभाषित URI से बचने के लिए लागू होता है ।


हमें उत्तर में "कैसे" चाहिए, "क्या" नहीं।
शिंज़ौ

11

दुर्भाग्य से, org.apache.commons.httpclient.util.URIUtilपदावनत किया जाता है, और replacement org.apache.commons.codec.net.URLCodecफॉर्म पोस्ट के लिए उपयुक्त कोडिंग करता है, वास्तविक URL में नहीं। तो मुझे अपना स्वयं का फ़ंक्शन लिखना था, जो एक एकल घटक है (जो पूरे क्वेरी स्ट्रिंग्स के लिए उपयुक्त नहीं है? 'S और' ')

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

चलो, एक पुस्तकालय होना चाहिए जो ऐसा करता है।
शिंज़ौ

9

URLEncoding HTTP URL को ठीक तरह से एनकोड कर सकता है, जैसा कि आपने दुर्भाग्य से खोजा है। आपके द्वारा पारित स्ट्रिंग, " http://search.barnesandnoble.com/booksearch/first book.pdf", सही ढंग से और पूरी तरह से URL- एन्कोडेड रूप में एन्कोड किया गया था। आप gobbledigook के उस पूरे लंबे स्ट्रिंग को पास कर सकते हैं जो आपको एक URL में एक पैरामीटर के रूप में वापस मिला है, और इसे वापस उसी स्ट्रिंग में डिकोड किया जा सकता है, जिसमें आप पास हुए थे।

ऐसा लगता है कि आप पूरे URL को एक पैरामीटर के रूप में पारित करने की तुलना में कुछ अलग करना चाहते हैं। मैं जो इकट्ठा करता हूं, आप " http://search.barnesandnoble.com/booksearch/whateverTheUserPassesIn " की तरह दिखने वाला एक खोज URL बनाने की कोशिश कर रहे हैं । केवल एक चीज जिसे आपको सांकेतिक शब्दों में बदलना चाहिए, वह है "जो भी TheUserPassesIn" बिट, इसलिए शायद आपको बस इतना करना है कि कुछ इस तरह है:

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

यह आपके लिए कुछ और अधिक मान्य होना चाहिए।


17
यह "+" के साथ userInput में रिक्त स्थान को बदल देगा। पोस्टर को उन्हें "20%" के साथ बदलने की आवश्यकता है।
23

@vocaro: यह एक बहुत अच्छा बिंदु है। URLEncoder तर्कों की तरह बच निकलता है, बाकी URL की तरह नहीं।
ब्रैंडन यारब्रॉट

9

यदि कोई अपनी परियोजना के लिए निर्भरता नहीं जोड़ना चाहता है, तो ये कार्य सहायक हो सकते हैं।

हम अपने 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 का उपयोग करने की आवश्यकता है?
N00b Pr0grammer

% 20
Cuga

7

आपके URL में एन्कोडेड "/" (% 2F) होने पर अभी भी एक समस्या है।

RFC 3986 - धारा 2.2 में कहा गया है: "यदि एक URI घटक के लिए डेटा एक आरक्षित चरित्र के उद्देश्य के साथ एक सीमांकक के रूप में संघर्ष करेगा, तो विरोधी डेटा URI के बनने से पहले प्रतिशत-एन्कोडेड होना चाहिए।" (RFC 3986 - धारा 2.2)

लेकिन टॉमकैट के साथ एक मुद्दा है:

http://tomcat.apache.org/security-6.html - Apache Tomcat 6.0.10 में फिक्स्ड

महत्वपूर्ण: निर्देशिका ट्रैवर्सल CVE-2007-0450

टॉमकैट '\', '% 2F' और '% 5C' [...] की अनुमति देता है।

URL में पथ के सीमांकक के अतिरिक्त नियंत्रण को प्रदान करने के लिए निम्नलिखित जावा सिस्टम के गुणों को टॉमकैट में जोड़ा गया है (दोनों विकल्प झूठे डिफ़ॉल्ट):

  • org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: सत्य और असत्य |
  • org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: सच | गलत |

यह गारंटी देने की असंभवता के कारण कि सभी URL को Tomcat द्वारा नियंत्रित किया जाता है, क्योंकि वे प्रॉक्सी सर्वर में हैं, Tomcat को हमेशा सुरक्षित रखा जाना चाहिए जैसे कि कोई प्रॉक्सी प्रतिबंधित संदर्भ पहुँच का उपयोग नहीं किया गया था।

प्रभावित: 6.0.0-6.0.9

तो अगर आपको% 2F वर्ण के साथ एक URL मिला है, तो Tomcat रिटर्न: "400 अमान्य URI: noSash"

आप Tomcat स्टार्टअप स्क्रिप्ट में बगफिक्स को स्विच कर सकते हैं:

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

7

मैंने अपनी स्वयं की विधि लिखने के लिए पिछले उत्तरों को पढ़ा क्योंकि मैं पिछले उत्तरों के समाधान का उपयोग करके ठीक से काम नहीं कर सकता था, यह मेरे लिए अच्छा लगता है लेकिन यदि आप ऐसा 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", "%"));
}

4

मैं मैट से सहमत हूं। वास्तव में, मैंने इसे ट्यूटोरियल में अच्छी तरह से समझाया कभी नहीं देखा है, लेकिन एक मामला यह है कि URL पथ को कैसे एन्कोड किया जाए, और एक बहुत ही अलग है कि कैसे उन मापदंडों को एनकोड किया जाए जो URL (क्वेरी भाग,) के पीछे संलग्न हैं? " प्रतीक)। वे समान एन्कोडिंग का उपयोग करते हैं, लेकिन समान नहीं।

विशेष रूप से सफेद अंतरिक्ष वर्ण के एन्कोडिंग के लिए। URL पथ को% 20 के रूप में एन्कोड किया जाना चाहिए, जबकि क्वेरी भाग% 20 और "+" चिह्न की भी अनुमति देता है। सबसे अच्छा विचार यह है कि वेब ब्राउजर का उपयोग करके अपने वेब सर्वर के खिलाफ खुद ही इसका परीक्षण करें।

दोनों मामलों के लिए, मैं हमेशा पूरे घटक का संयोजन करूंगा , पूरे स्ट्रिंग को कभी नहीं। वास्तव में URLEncoder क्वेरी भाग के लिए अनुमति देता है। पथ भाग के लिए आप क्लास यूआरआई का उपयोग कर सकते हैं, हालांकि इस मामले में यह पूरे स्ट्रिंग के लिए पूछता है, एक भी घटक नहीं।

वैसे भी, मेरा मानना ​​है कि इन समस्याओं से बचने का सबसे अच्छा तरीका एक व्यक्तिगत गैर-हिंसक डिजाइन का उपयोग करना है। कैसे? उदाहरण के लिए, मैं कभी भी aZ, AZ, 0-9 और _ के अलावा अन्य वर्णों का उपयोग करके निर्देशिकाओं या मापदंडों का नाम नहीं दूंगा। इस तरह, केवल आवश्यकता हर पैरामीटर के मान को एनकोड करने की है, क्योंकि यह उपयोगकर्ता इनपुट से आ सकता है और उपयोग किए गए अक्षर अज्ञात हैं।


2
प्रश्न में URL का उपयोग करने वाला नमूना कोड आपके उत्तर में डालने के लिए एक अच्छी बात होगी
मार्टिन सेरानो


3

आप GUAVAएस्कैपर का उपयोग और पथ कर सकते हैं : UrlEscapers.urlFragmentEscaper().escape(relativePath)


2

कार्लोस हेबर्गर के उत्तर के अलावा: यदि डिफॉल्ट (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();

2

मैंने सामग्री ऊपर ले ली और इसे थोड़ा बदल दिया। मुझे पहले सकारात्मक तर्क पसंद हैं, और मैंने सोचा कि एक हैशसेट कुछ अन्य विकल्पों की तुलना में बेहतर प्रदर्शन दे सकता है, जैसे एक स्ट्रिंग के माध्यम से खोज करना। हालांकि, मुझे यकीन नहीं है कि अगर ऑटोबॉक्सिंग जुर्माना इसके लायक है, लेकिन यदि कंपाइलर 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);
}

1

निम्नलिखित मानक जावा समाधान का उपयोग करें ( वेब प्लैटफॉर्म टेस्ट द्वारा प्रदान किए गए लगभग 100 परीक्षण पास ):

0. यदि URL पहले से एन्कोडेड है तो टेस्ट करें

1. संरचनात्मक भागों में URL विभाजित करें। java.net.URL इसके लिए उपयोग करें ।

2. प्रत्येक संरचनात्मक भाग को ठीक से एनकोड करें!

3. पुन्यकोड का उपयोग होस्ट नाम IDN.toASCII(putDomainNameHere)को एनकोड करें !

4.java.net.URI.toASCIIString() प्रतिशत-एनकोड करने के लिए उपयोग करें , एनएफसी एनकोडेड यूनिकोड - (बेहतर होगा NFKC!)।

यहां और अधिक जानकारी प्राप्त करें: https://stackoverflow.com/a/49796882/1485527


0

मैंने 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


0

मुझे भी यही समस्या थी। इसे एकजुट करके हल किया गया:

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

यह स्ट्रिंग को एनकोड करता है लेकिन ":" और "/" को छोड़ देता है।


0

मैं इस का उपयोग करें

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

इस भरोसे को जोड़ें

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

-2

मैं एक पुस्तकालय विकसित करता हूं जो इस उद्देश्य को पूरा करता है: गैलिमियास । यह उसी तरह से URL देता है जैसे वेब ब्राउज़र करते हैं। यही है, अगर कोई URL ब्राउज़र में काम करता है, तो यह गैलिमियास द्वारा सही ढंग से पार्स किया जाएगा

इस मामले में:

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


-3

आप इस तरह के एक समारोह का उपयोग कर सकते हैं। अपनी आवश्यकता को पूरा और संशोधित करें:

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


1
यह उत्तर URLCodec के बिना अधूरा है।
लोर्न

.replace () चाइनिंग के लिए upvote, यह आदर्श नहीं है, लेकिन यह बुनियादी तदर्थ उपयोग के मामलों के लिए पर्याप्त है
svarog

-5

स्ट्रिंग url = "" http://search.barnesandnoble.com/booksearch/ ;

यह निरंतर मुझे लगता है और केवल फ़ाइल नाम परिवर्तन dyamically तो फ़ाइल नाम हो जाएगा

स्ट्रिंग फ़ाइल नाम; // फ़ाइल नाम प्राप्त करें

स्ट्रिंग urlEnc = url + fileName.replace ("", "% 20");


2
अन्य सभी अवैध पात्रों के बारे में क्या?
लोर्ने

-7

कैसा रहेगा:

सार्वजनिक स्ट्रिंग UrlEncode (स्ट्रिंग in_) {

String retVal = "";

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

return retVal;

}


URLEncoder का उपयोग ivalid URL वर्णों से बचने के लिए नहीं किया जा सकता है। केवल रूपों को सांकेतिक शब्दों में बदलना।
आर्चर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.