Mon application autonome Java obtient une URL (qui pointe vers un fichier) de l'utilisateur et je dois la frapper et la télécharger. Le problème auquel je suis confronté est que je ne suis pas en mesure de coder correctement l'adresse URL HTTP ...
Exemple:
URL: http://search.barnesandnoble.com/booksearch/first book.pdf
java.net.URLEncoder.encode(url.toString(), "ISO-8859-1");
me renvoie:
http%3A%2F%2Fsearch.barnesandnoble.com%2Fbooksearch%2Ffirst+book.pdf
Mais ce que je veux c'est
http://search.barnesandnoble.com/booksearch/first%20book.pdf
(espace remplacé par% 20)
Je suppose qu'il URLEncoder
n'est pas conçu pour encoder des URL HTTP ... Le JavaDoc dit "Classe utilitaire pour l'encodage de formulaires HTML" ... Y a-t-il une autre façon de le faire?
Réponses:
La classe java.net.URI peut vous aider; dans la documentation de l'URL que vous trouvez
Utilisez l'un des constructeurs avec plus d'un argument, comme:
(le constructeur à un seul argument de l'URI n'échappe PAS aux caractères illégaux)
Seuls les caractères illégaux sont échappés par le code ci-dessus - il n'échappe PAS aux caractères non ASCII (voir le commentaire de fatih).
La
toASCIIString
méthode peut être utilisée pour obtenir une chaîne uniquement avec des caractères US-ASCII:Pour une URL avec une requête comme
http://www.google.com/ig/api?weather=São Paulo
, utilisez la version à 5 paramètres du constructeur:la source
java.net.URI
: elle fonctionnait parfaitement (Java 1.6). Je mentionnerais le nom de classe complet s'il n'était pas celui de Java standard et le lien pointe vers la documentation dejava.net.URI
. Et, par le commentaire de Sudhakar, cela a résolu le problème sans inclure de "bibliothèques communes"!Veuillez noter que la plupart des réponses ci-dessus sont incorrectes.
La
URLEncoder
classe, malgré son nom, n'est PAS ce qui doit être ici. Il est malheureux que Sun ait nommé cette classe de façon si ennuyeuse.URLEncoder
est destiné à transmettre des données en tant que paramètres, pas à encoder l'URL elle-même.En d'autres termes,
"http://search.barnesandnoble.com/booksearch/first book.pdf"
c'est l'URL. Les paramètres seraient, par exemple"http://search.barnesandnoble.com/booksearch/first book.pdf?parameter1=this¶m2=that"
,. Les paramètres sont ceux que vous utiliseriezURLEncoder
.Les deux exemples suivants mettent en évidence les différences entre les deux.
Ce qui suit produit les mauvais paramètres, selon la norme HTTP. Notez que l'esperluette (&) et le signe plus (+) ne sont pas encodés correctement.
Ce qui suit produira les paramètres corrects, avec la requête correctement encodée. Notez les espaces, les esperluettes et les marques plus.
la source
query = URLEncoder.encode(key) + "=" + URLEncoder.encode(value)
. Les documents indiquent simplement que "tout caractère qui n'est pas un caractère URI légal est cité".Je vais ajouter une suggestion ici destinée aux utilisateurs d'Android. Vous pouvez le faire, ce qui évite d'avoir à obtenir des bibliothèques externes. En outre, toutes les solutions de recherche / remplacement de caractères suggérées dans certaines des réponses ci-dessus sont périlleuses et doivent être évitées.
Essayez ceci:
Vous pouvez voir que dans cette URL particulière, j'ai besoin d'avoir ces espaces encodés afin de pouvoir l'utiliser pour une demande.
Cela profite de quelques fonctionnalités disponibles dans les classes Android. Tout d'abord, la classe URL peut décomposer une URL en ses composants appropriés, il n'est donc pas nécessaire que vous effectuiez un travail de recherche / remplacement de chaîne. Deuxièmement, cette approche tire parti de la fonctionnalité de classe URI consistant à échapper correctement les composants lorsque vous construisez un URI via des composants plutôt qu'à partir d'une seule chaîne.
La beauté de cette approche est que vous pouvez prendre n'importe quelle chaîne d'URL valide et la faire fonctionner sans avoir besoin de connaissances particulières vous-même.
la source
#
.une solution que j'ai développée et beaucoup plus stable que toute autre:
la source
String utf8Input = new String(Charset.forName("UTF-8").encode(input).array());
(extrait d' ici )Si vous avez une URL, vous pouvez transmettre url.toString () à cette méthode. Décodez d'abord, pour éviter le double codage (par exemple, le codage d'un espace donne% 20 et le codage d'un signe de pourcentage donne% 25, donc le double codage transformera un espace en% 2520). Ensuite, utilisez l'URI comme expliqué ci-dessus, en ajoutant toutes les parties de l'URL (afin de ne pas supprimer les paramètres de requête).
la source
Ouais, l'encodage d'URL va encoder cette chaîne afin qu'elle soit passée correctement dans une URL vers une destination finale. Par exemple, vous ne pouvez pas avoir http://stackoverflow.com?url=http://yyy.com . UrlEncoding le paramètre fixerait cette valeur de paramètre.
J'ai donc deux choix pour vous:
Avez-vous accès au chemin d'accès séparé du domaine? Si c'est le cas, vous pourrez peut-être simplement UrlEncode le chemin. Cependant, si ce n'est pas le cas, l'option 2 peut être pour vous.
Obtenez commons-httpclient-3.1. Cela a une classe URIUtil:
System.out.println (URIUtil.encodePath (" http://example.com/x y", "ISO-8859-1"));
Cela produira exactement ce que vous recherchez, car il ne codera que la partie chemin de l'URI.
Pour info, vous aurez besoin de commons-codec et commons-logging pour que cette méthode fonctionne lors de l'exécution.
la source
URIUtil
solutionNitpicking: une chaîne contenant un espace blanc par définition n'est pas un URI. Donc, ce que vous recherchez, c'est du code qui implémente l'échappement URI défini dans la section 2.1 de la RFC 3986 .
la source
Malheureusement, il
org.apache.commons.httpclient.util.URIUtil
est obsolète et lereplacement org.apache.commons.codec.net.URLCodec
codage ne convient pas aux publications de formulaire, pas dans les URL réelles. J'ai donc dû écrire ma propre fonction, qui fait un seul composant (ne convient pas aux chaînes de requête entières qui ont des? Et des)la source
URLEncoding peut très bien encoder les URL HTTP, comme vous l'avez malheureusement découvert. La chaîne que vous avez transmise, " http://search.barnesandnoble.com/booksearch/first book.pdf", était correctement et complètement codée dans un formulaire codé URL. Vous pouvez transmettre toute la longue chaîne de charabia que vous avez récupérée en tant que paramètre dans une URL, et elle peut être décodée exactement dans la chaîne que vous avez transmise.
Il semble que vous souhaitiez faire quelque chose d'un peu différent que de passer l'URL entière en tant que paramètre. D'après ce que je comprends, vous essayez de créer une URL de recherche qui ressemble à " http://search.barnesandnoble.com/booksearch/wwhatTheUserPassesIn ". La seule chose dont vous avez besoin pour encoder est le bit "anyTheUserPassesIn", donc peut-être que tout ce que vous avez à faire est quelque chose comme ceci:
Cela devrait produire quelque chose de plus valable pour vous.
la source
Si quelqu'un ne veut pas ajouter de dépendance à son projet, ces fonctions peuvent être utiles.
Nous passons ici la partie «chemin» de notre URL. Vous ne voulez probablement pas transmettre l'URL complète en tant que paramètre (les chaînes de requête nécessitent des échappements différents, etc.).
Et des tests:
la source
Il y a toujours un problème si vous avez un "/" codé (% 2F) dans votre URL.
RFC 3986 - La section 2.2 dit: "Si les données d'un composant URI entraient en conflit avec l'objectif d'un caractère réservé en tant que délimiteur, alors les données en conflit doivent être codées en pourcentage avant que l'URI ne soit formé." (RFC 3986 - section 2.2)
Mais il y a un problème avec Tomcat:
Donc, si vous avez une URL avec le caractère% 2F, Tomcat retourne: "400 URI invalide: noSlash"
Vous pouvez désactiver le correctif dans le script de démarrage de Tomcat:
la source
J'ai lu les réponses précédentes pour écrire ma propre méthode car je ne pouvais pas faire fonctionner correctement quelque chose en utilisant la solution des réponses précédentes, cela me semble bien, mais si vous pouvez trouver une URL qui ne fonctionne pas avec cela, veuillez me le faire savoir.
la source
Je suis d'accord avec Matt. En effet, je ne l'ai jamais vu bien expliqué dans les didacticiels, mais une question est de savoir comment coder le chemin URL, et une toute autre est de savoir comment coder les paramètres qui sont ajoutés à l'URL (la partie requête, derrière le "? " symbole). Ils utilisent un encodage similaire, mais pas le même.
Spécialement pour l'encodage du caractère d'espace blanc. Le chemin URL doit être codé en% 20, tandis que la partie requête autorise% 20 et également le signe "+". La meilleure idée est de le tester par nous-mêmes sur notre serveur Web, à l'aide d'un navigateur Web.
Dans les deux cas, JE TOUJOURS coderais COMPOSANT PAR COMPOSANT , jamais la chaîne entière. En effet, URLEncoder le permet pour la partie requête. Pour la partie chemin, vous pouvez utiliser l'URI de classe, bien que dans ce cas, il demande la chaîne entière, pas un seul composant.
Quoi qu'il en soit, je crois que la meilleure façon d'éviter ces problèmes est d'utiliser une conception personnelle non conflictuelle. Comment? Par exemple, je ne nommerais jamais de répertoires ou de paramètres utilisant d'autres caractères que aZ, AZ, 0-9 et _. De cette façon, le seul besoin est de coder la valeur de chaque paramètre, car il peut provenir d'une entrée utilisateur et les caractères utilisés sont inconnus.
la source
Peut-être pouvez-vous essayer UriUtils dans org.springframework.web.util
la source
Vous pouvez également utiliser
GUAVA
et utiliser Escaper:UrlEscapers.urlFragmentEscaper().escape(relativePath)
la source
En plus de la réponse de Carlos Heuberger: si un autre que le défaut (80) est nécessaire, le constructeur 7 param doit être utilisé:
la source
J'ai pris le contenu ci-dessus et l'ai changé un peu. J'aime d'abord la logique positive et je pensais qu'un HashSet pourrait donner de meilleures performances que certaines autres options, comme la recherche dans une chaîne. Bien que je ne sois pas sûr que la pénalité d'autoboxing en vaille la peine, mais si le compilateur optimise pour les caractères ASCII, le coût de la boxe sera faible.
la source
Utilisez la solution Java standard suivante (passe environ 100 des cas de test fournis par Web Plattform Tests ):
0. Testez si l'URL est déjà encodée .
1. Split URL en parties structurelles. Utilisez
java.net.URL
pour cela.2. Codez correctement chaque pièce structurelle!
3. Utilisez
IDN.toASCII(putDomainNameHere)
pour Punycode encoder le nom d'hôte!4. Utilisez
java.net.URI.toASCIIString()
pour coder en pourcentage, unicode codé NFC - (mieux serait NFKC!).Trouvez plus ici: https://stackoverflow.com/a/49796882/1485527
la source
J'ai créé un nouveau projet pour aider à construire des URL HTTP. La bibliothèque encodera automatiquement les segments de chemin et les paramètres de requête par URL.
Vous pouvez afficher la source et télécharger un binaire sur https://github.com/Widen/urlbuilder
L'URL d'exemple dans cette question:
produit
http://search.barnesandnoble.com/booksearch/first%20book.pdf
la source
J'ai eu le même problème. Résolu ce problème en supprimant:
Il code la chaîne mais ignore ":" et "/".
la source
j'utilise ceci
ajouter cette dépendance
la source
Je développe une bibliothèque à cet effet: les galimatias . Il analyse l'URL de la même manière que les navigateurs Web. Autrement dit, si une URL fonctionne dans un navigateur, elle sera correctement analysée par les galimatias .
Dans ce cas:
Vous donnera:
http://search.barnesandnoble.com/booksearch/first%20book.pdf
. Bien sûr, c'est le cas le plus simple, mais cela fonctionnera avec n'importe quoi, bien au-delàjava.net.URI
.Vous pouvez le vérifier sur: https://github.com/smola/galimatias
la source
Vous pouvez utiliser une fonction comme celle-ci. Complétez et modifiez-le selon vos besoins:
Exemple d'utilisation:
Le résultat est: http://www.growup.com/folder/int%C3%A9rieur-%C3%A0_vendre?o=4
la source
String url = "" http://search.barnesandnoble.com/booksearch/ ;
Ce sera constant, je suppose, et seul le nom de fichier change de manière dynamique, alors obtenez le nom de fichier
String filename; // récupère le nom du fichier
String urlEnc = url + fileName.replace ("", "% 20");
la source
Que diriez-vous:
public String UrlEncode (String in_) {
}
la source