Moja samodzielna aplikacja Java pobiera adres URL (który wskazuje na plik) od użytkownika i muszę go nacisnąć i pobrać. Problem, przed którym stoję, polega na tym, że nie jestem w stanie poprawnie zakodować adresu URL HTTP ...
Przykład:
URL: http://search.barnesandnoble.com/booksearch/first book.pdf
java.net.URLEncoder.encode(url.toString(), "ISO-8859-1");
zwraca mi:
http%3A%2F%2Fsearch.barnesandnoble.com%2Fbooksearch%2Ffirst+book.pdf
Ale chcę tego
http://search.barnesandnoble.com/booksearch/first%20book.pdf
(spacja zastąpiona przez% 20)
URLEncoder
Wydaje mi się, że nie jest przeznaczony do kodowania adresów URL HTTP ... JavaDoc mówi „Klasa użytkowa do kodowania formularzy HTML” ... Czy jest jakiś inny sposób to zrobić?
Odpowiedzi:
Java.net.URI klasa może pomóc; w dokumentacji znalezionego adresu URL
Użyj jednego z konstruktorów z więcej niż jednym argumentem, na przykład:
(konstruktor URI z jednym argumentem NIE ucieka przed niedozwolonymi znakami)
Tylko niedozwolone znaki są usuwane przez powyższy kod - NIE ucieka to znaków spoza ASCII (patrz komentarz fatih). Metoda może być stosowana, aby uzyskać ciąg znaków tylko z US-ASCII:
toASCIIString
W przypadku adresu URL z zapytaniem podobnym
http://www.google.com/ig/api?weather=São Paulo
użyj 5-parametrowej wersji konstruktora:źródło
java.net.URI
: działała idealnie (Java 1.6). Wspomniałbym w pełni kwalifikowaną nazwę klasy, gdyby nie była standardową nazwą Java, a link wskazuje na dokumentacjęjava.net.URI
. I dzięki komentarzowi Sudhakara rozwiązał problem bez uwzględnienia „wspólnych bibliotek”!Należy pamiętać, że większość powyższych odpowiedzi jest NIEPRAWIDŁOWA.
URLEncoder
Klasy, mimo to nazwisko, a nie to, co musi być tutaj. Szkoda, że Sun nazwał tę klasę tak irytująco.URLEncoder
służy do przekazywania danych jako parametrów, a nie do kodowania samego adresu URL.Innymi słowy,
"http://search.barnesandnoble.com/booksearch/first book.pdf"
to adres URL. Parametry to na przykład"http://search.barnesandnoble.com/booksearch/first book.pdf?parameter1=this¶m2=that"
. Parametry są do tego użyteURLEncoder
.Poniższe dwa przykłady podkreślają różnice między nimi.
Poniżej przedstawiono nieprawidłowe parametry, zgodnie ze standardem HTTP. Zwróć uwagę, że znaki ampersand (&) i plus (+) są niepoprawnie kodowane.
Poniższe spowoduje wygenerowanie poprawnych parametrów z poprawnie zakodowanym zapytaniem. Zwróć uwagę na spacje, znaki handlowe i znaki plus.
źródło
query = URLEncoder.encode(key) + "=" + URLEncoder.encode(value)
. Dokumenty mówią tylko, że „cytowany jest dowolny znak, który nie jest legalnym znakiem URI”.Dodam tutaj jedną sugestię skierowaną do użytkowników Androida. Możesz to zrobić, co pozwala uniknąć pobierania zewnętrznych bibliotek. Ponadto wszystkie rozwiązania wyszukiwania / zamiany znaków sugerowane w niektórych powyższych odpowiedziach są niebezpieczne i należy ich unikać.
Wypróbuj to:
Widać, że w tym konkretnym adresie URL muszę zakodować te spacje, aby móc użyć go do żądania.
Wykorzystuje to kilka funkcji dostępnych w klasach Androida. Po pierwsze, klasa URL może rozbić adres URL na odpowiednie komponenty, więc nie trzeba wykonywać żadnych operacji wyszukiwania / zamiany łańcucha. Po drugie, w tym podejściu wykorzystuje się właściwość klasy URI polegającą na prawidłowym ucieczce komponentów podczas konstruowania identyfikatora URI za pomocą komponentów, a nie pojedynczego łańcucha.
Piękno tego podejścia polega na tym, że możesz wziąć dowolny prawidłowy ciąg adresu URL i sprawić, aby działał bez potrzeby specjalnej wiedzy na jego temat.
źródło
#
.rozwiązanie, które opracowałem i jest znacznie bardziej stabilne niż jakiekolwiek inne:
źródło
String utf8Input = new String(Charset.forName("UTF-8").encode(input).array());
(pobranego stąd )Jeśli masz adres URL, możesz przekazać metodę url.toString () do tej metody. Najpierw dekoduj, aby uniknąć podwójnego kodowania (na przykład kodowanie spacji powoduje% 20, a kodowanie znaku procentu powoduje% 25, więc podwójne kodowanie zamieni spację w% 2520). Następnie użyj identyfikatora URI, jak wyjaśniono powyżej, dodając wszystkie części adresu URL (aby nie upuścić parametrów zapytania).
źródło
Tak, kodowanie URL będzie kodować ten ciąg, aby był poprawnie przekazywany w adresie URL do miejsca docelowego. Na przykład nie możesz mieć http://stackoverflow.com?url=http://yyy.com . UrlEncoding parametru naprawi tę wartość parametru.
Mam dla ciebie dwie możliwości:
Czy masz dostęp do ścieżki niezależnej od domeny? Jeśli tak, możesz po prostu UrlEncode ścieżkę. Jeśli jednak tak nie jest, opcja 2 może być dla Ciebie.
Pobierz commons-httpclient-3.1. Ma to klasę URIUtil:
System.out.println (URIUtil.encodePath („ http://example.com/x y”, „ISO-8859-1”));
Spowoduje to wyświetlenie dokładnie tego, czego szukasz, ponieważ koduje tylko część ścieżki URI.
Do twojej metody będziesz potrzebował kodera-dekodera i logowania do wspólnego, aby ta metoda działała w czasie wykonywania.
źródło
URIUtil
rozwiązaniaNitpicking: ciąg znaków z definicji spacją nie jest identyfikatorem URI. Tak więc szukasz kodu, który implementuje ucieczkę URI zdefiniowany w Sekcji 2.1 RFC 3986 .
źródło
Niestety
org.apache.commons.httpclient.util.URIUtil
jest przestarzałe, areplacement org.apache.commons.codec.net.URLCodec
kodowanie nadaje się do postów, a nie rzeczywistych adresów URL. Musiałem więc napisać własną funkcję, która wykonuje pojedynczy komponent (nieodpowiedni dla całych ciągów zapytań zawierających? I &)źródło
URLEncoding potrafi dobrze kodować adresy URL HTTP, co niestety odkryłeś. Przekazany ciąg „ http://search.barnesandnoble.com/booksearch/first book.pdf” został poprawnie i całkowicie zakodowany w postaci zakodowanej w adresie URL. Możesz przekazać cały długi ciąg gobbledigook, który dostałeś jako parametr w adresie URL, i można go dekodować z powrotem do dokładnie tego, który przekazałeś.
Wygląda na to, że chcesz zrobić coś innego niż przekazywanie całego adresu URL jako parametru. Z tego, co zbieram, próbujesz utworzyć URL wyszukiwania, który wygląda jak „ http://search.barnesandnoble.com/booksearch/whthingTheUserPassesIn ”. Jedyne, co musisz zakodować, to bit „whatTheUserPassesIn”, więc być może wszystko, co musisz zrobić, to coś takiego:
To powinno dać ci coś bardziej odpowiedniego dla ciebie.
źródło
Jeśli ktoś nie chce dodawać zależności do swojego projektu, te funkcje mogą być pomocne.
Przekazujemy tutaj część „ścieżki” naszego adresu URL. Prawdopodobnie nie chcesz przekazać pełnego adresu URL jako parametru (ciągi zapytania wymagają różnych znaków zmiany znaczenia itp.).
I testy:
źródło
Nadal występuje problem, jeśli masz zakodowany „/” (% 2F) w swoim adresie URL.
RFC 3986 - Sekcja 2.2 mówi: „Jeśli dane dla komponentu URI byłyby sprzeczne z celem znaku zarezerwowanego jako separatora, wówczas konfliktowe dane muszą zostać zakodowane procentowo przed utworzeniem URI”. (RFC 3986 - sekcja 2.2)
Ale jest problem z Tomcat:
Więc jeśli masz adres URL ze znakiem% 2F, Tomcat zwraca: „400 Nieprawidłowy identyfikator URI: noSlash”
Możesz przełączyć poprawkę w skrypcie startowym Tomcat:
źródło
Przeczytałem poprzednie odpowiedzi, aby napisać własną metodę, ponieważ nie mogłem mieć czegoś poprawnie działającego przy użyciu rozwiązania poprzednich odpowiedzi, wygląda to dla mnie dobrze, ale jeśli możesz znaleźć URL, który nie działa z tym, daj mi znać.
źródło
Zgadzam się z Mattem. Rzeczywiście, nigdy nie widziałem tego dobrze wyjaśnionego w samouczkach, ale jedną kwestią jest to, jak zakodować ścieżkę adresu URL, a zupełnie inną kwestią jest sposób kodowania parametrów, które są dołączane do adresu URL (część zapytania, za „? „symbol). Używają podobnego kodowania, ale nie tego samego.
Specjalnie do kodowania znaku białych znaków. Ścieżka adresu URL wymaga zakodowania jako% 20, podczas gdy część zapytania umożliwia% 20, a także znak „+”. Najlepszym pomysłem jest przetestowanie go na własnym serwerze internetowym za pomocą przeglądarki internetowej.
W obu przypadkach ZAWSZE kodowałbym COMPONENT BY COMPONENT , nigdy cały łańcuch. Rzeczywiście URLEncoder pozwala na to w części zapytania. Do części ścieżki można użyć identyfikatora URI klasy, chociaż w tym przypadku prosi on o cały ciąg, a nie o pojedynczy komponent.
W każdym razie uważam, że najlepszym sposobem na uniknięcie tych problemów jest zastosowanie osobistego, nie powodującego konfliktu projektu. W jaki sposób? Na przykład nigdy nie nazwałbym katalogów ani parametrów przy użyciu znaków innych niż aZ, AZ, 0-9 i _. W ten sposób wystarczy zakodować wartość każdego parametru, ponieważ może on pochodzić z danych wejściowych użytkownika, a użyte znaki są nieznane.
źródło
Może może wypróbować UriUtils w org.springframework.web.util
źródło
Możesz także użyć
GUAVA
escapera i ścieżki:UrlEscapers.urlFragmentEscaper().escape(relativePath)
źródło
Oprócz odpowiedzi Carlosa Heubergera: jeśli potrzebny jest inny niż domyślny (80), należy użyć konstruktora 7 param:
źródło
Wziąłem powyższą treść i nieco ją zmieniłem. Najpierw lubię logikę pozytywną i pomyślałem, że zestaw HashSet może dać lepszą wydajność niż niektóre inne opcje, takie jak przeszukiwanie ciągu. Chociaż nie jestem pewien, czy kara z tytułu autoboxowania jest tego warta, ale jeśli kompilator zoptymalizuje się pod znaki ASCII, to koszt boksu będzie niski.
źródło
Użyj następującego standardowego rozwiązania Java (przechodzi około 100 przypadków testowych dostarczonych przez Web Plattform Tests ):
0. Sprawdź, czy adres URL jest już zakodowany .
1. Podziel adres URL na części strukturalne. Użyj
java.net.URL
do tego.2. Zakoduj poprawnie każdą część konstrukcyjną!
3. Użyj
IDN.toASCII(putDomainNameHere)
aby Punycode zakodować nazwę hosta!4. Użyj
java.net.URI.toASCIIString()
do kodowania procentowego, kodowania NFC unicode - (lepiej byłoby NFKC!).Znajdź więcej tutaj: https://stackoverflow.com/a/49796882/1485527
źródło
Stworzyłem nowy projekt, aby pomóc w tworzeniu adresów URL HTTP. Biblioteka automatycznie koduje adresy URL segmentów ścieżki i parametry zapytania.
Możesz wyświetlić źródło i pobrać plik binarny na https://github.com/Widen/urlbuilder
Przykładowy adres URL w tym pytaniu:
produkuje
http://search.barnesandnoble.com/booksearch/first%20book.pdf
źródło
Miałem ten sam problem. Rozwiązano to przez:
Koduje ciąg, ale pomija „:” i „/”.
źródło
używam tego
dodaj tę zależność
źródło
Tworzę bibliotekę, która służy temu celowi: galimatias . Analizuje adres URL w taki sam sposób jak przeglądarki internetowe. Oznacza to, że jeśli URL działa w przeglądarce, zostanie poprawnie przeanalizowany przez galimatias .
W tym przypadku:
Daje:
http://search.barnesandnoble.com/booksearch/first%20book.pdf
. Oczywiście jest to najprostszy przypadek, ale będzie działał z wszystkim, nawet dalekojava.net.URI
.Możesz to sprawdzić na stronie : https://github.com/smola/galimatias
źródło
Możesz użyć takiej funkcji. Uzupełnij i zmodyfikuj według swoich potrzeb:
Przykład zastosowania:
Wynik jest następujący: http://www.growup.com/folder/int%C3%A9rieur-%C3%A0_vendre?o=4
źródło
String url = "" http://search.barnesandnoble.com/booksearch/ ;
Myślę, że będzie to stała i tylko nazwa pliku zmienia się drastycznie, więc pobierz nazwę pliku
Nazwa pliku ciągu; // pobierz nazwę pliku
Ciąg urlEnc = url + nazwa_pliku.replace ("", "% 20");
źródło
Co powiesz na:
public String UrlEncode (String in_) {
}
źródło