IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

[HttpURLConnection] HTTP 505 espace dans nom de fichier


Sujet :

Langage Java

  1. #1
    Membre chevronné
    Avatar de ska_root
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    1 203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Service public

    Informations forums :
    Inscription : Août 2005
    Messages : 1 203
    Points : 1 839
    Points
    1 839
    Par défaut [HttpURLConnection] HTTP 505 espace dans nom de fichier
    Bonjour (et bonne année !),

    J'ai un souci lors de la récupération d'un fichier via HttpURLConnection. Je sais que l'erreur provient d'espaces dans le nom de fichier mais ne trouve pas de solution pour contourner le problème.

    J'utilise la classe URL pour la requete initiale (le serveur utilise les friendly's url)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    URL url = new URL("http://distant/mon-fichier");
    le serveur distant redirige la requete vers le fichier à distribuer, cela fonctionne trés bien sur un fichier dont le nom ne contient pas d'espace.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    HttpURLConnection cnx= (HttpURLConnection) url.openConnection();
    cnx.getContent();
    /* 
    java.io.IOException: Server returned HTTP response code: 505 for URL: http://distant/upload/mon fichier.pdf 
    */
    évidemment en tapant directement "http://distant/upload/mon%20fichier.pdf" dans le navigateur, j'obtiens bien mon pdf...

    ma question : comment intervenir dans HttpURLConnection pour encoder l'URL de redirection renvoyée par le serveur ?

    serveur distant : Tomcat 5.5 / JDK1.5.0
    serveur local: Tomcat 6 / JDK1.5.0

  2. #2
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 562
    Points : 15 502
    Points
    15 502

  3. #3
    Membre chevronné
    Avatar de ska_root
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    1 203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Service public

    Informations forums :
    Inscription : Août 2005
    Messages : 1 203
    Points : 1 839
    Points
    1 839
    Par défaut
    Merci de ta réponse Uther mais je ne vois pas où appliquer URLEncoder car l'adresse entrée dans URL n'a pas d'espace comme tu peux le constater...

    Cette adresse est traduite par le serveur distant qui redirige vers le fichier désiré...

    donc "http://distant/mon-fichier" devient "http://distant/upload/mon fichier.pdf" car c'est le nom (et l'emplacement) réel du fichier sur le serveur distant.

    il faudrait que je puisse intervenir avant que openConnection ne veuille récupèrer le stream...

  4. #4
    Membre chevronné
    Avatar de ska_root
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    1 203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Service public

    Informations forums :
    Inscription : Août 2005
    Messages : 1 203
    Points : 1 839
    Points
    1 839
    Par défaut
    J'ai trouvé !

    Pour ceux que cela intéresse :
    Il faut agir en deux temps, une première fois pour récupérer l'adresse de redirection, puis en modifiant le queryString à la mano, URLEncoder.endode() ne me donnant pas le résultat attendu (il met des "+" au lieu des "%20").
    Il existe peut-être plus propre, mais cela a au moins le mérite de fonctionner...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    try {
       URL url= new URL("http://distant/mon-fichier");
       HttpURLConnection uc= (HttpURLConnection) url.openConnection();
       uc.setInstanceFollowRedirects(false); // interdit la redirection du serveur
       uc.connect();
       String urlToModify= uc.getHeaderField("Location"); // recupere l'adresse redirigee
       uc.disconnect();
     
       // modification de l'URL retournee par le serveur
       String toKeep=urlToModify.substring(0,urlToModify.lastIndexOf("/")+1);
       String toEncode=urlToModify.substring(urlToModify.lastIndexOf("/")+1);
       String urlToCapture=toKeep+toEncode.replaceAll(" ","%20");
     
       // on peut maintenant recommencer la capture
       url=new URL(urlToCapture);
     
       // ... et voilà j'ai bien mon inputStream
       Object o= url.getContent();
       System.out.println(o); 
     
     
    }catch (MalformedURLException e) {
       logger.error("Erreur de syntaxe lors du chargement de l'URL", e);
    }catch (IOException e) {
       logger.error("Erreur de lecture du fichier", e);
    }catch (Exception e) {
       logger.error("Erreur inconnue lors du chargement de l'URL", e);
    }

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Attention car URLEncoder.encode() sert à encoder les paramètres et non pas les URLs et va donc également remplacer les :// et autres caractères réservées des URLs...



    A mon avis le problème vient de ton serveur, car d'après la doc lors d'une redirection il doit renvoyer une URI valide ce qui interdit les espaces : http://www.w3.org/Protocols/rfc2616/....html#sec14.30

    En clair c'est le serveur qui devrait encoder correctement l'URL. Cela marche quand même car les navigateurs sont plus tolérant, mais ce serait bel et bien la meilleure solution.



    Sinon tu pourrais passer par une API plus évolué, comme HttpClient de Jakarta, qui devrait gérer cela proprement et qui propose d'ailleurs tous les outils de gestions des URLs...





    Sinon en standard il faut déjà que tu encode correctement l'URL.
    Comme je l'ai dit URLEncoder ne peut pas être utilisé pour une URL entière, sauf à vouloir la passer en paramètre à une autre URL.
    En regardant rapidement la RFC sur les URIs cela devrait donner quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    	public static String encode(String str) {
    		// Listes des caractères réservés à remplacer :
    		final String reserved = " <>#%\"{}|\\^[]`";
     
    		final int SIZE = str.length();
    		final StringBuilder sb = new StringBuilder(SIZE);
    		for (int i=0; i<SIZE; i++) {
    			char c = str.charAt(i);
     
    			if (( c >= 0x7F ) // caractères non-ascii
    			 || ( c <= 0x1F ) // caractères de contrôle
    			 || ( reserved.indexOf(c) >= 0 ) ) {// caractères réservés
    				sb.append( String.format("%%%02x", (int)c) );				
    			} else {
    				sb.append(c);
    			}
    		}
    		return sb.toString();
    	}
    Le problème c'est que si tu encodes alors que c'est déjà fait tu te retrouve avec une URLs incorrecte



    Maintenant en standard tu as deux solutions :
    [list][*]Soit tu désactives la gestion automatique des redirections via setInstanceFollowRedirects(false), mais cela implique un traitement plus lourd pour toi car tu devras gérer cela manuellement, c'est à dire vérifier le Status pour traiter les redirections (code 3XX), puis générer l'URL définitive via le header "Location".
    Autant te dire que cela doit être assez pénible
    Surtout qu'il faut éviter d'encoder quelque chose qui ne devrait pas l'être...

    [*]Soit tu fais un post-traitement en cas d'erreur, où tu essayes de corriger l'URL en cas d'erreur.
    C'est à mon avis la solution la plus simple...


    Par exemple au lieu d'avoir quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	public Object getContent(URL url) throws IOException {
    		URLConnection cnx = url.openConnection();
    		return cnx.getContent();
    	}
    On pourrait faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    	public Object getContent(URL url) throws IOException {
    		return getContent(url, 5);
    	}
     
    	public Object getContent(URL url, int maxcount) throws IOException {
    		URLConnection cnx = url.openConnection();
    		try {
    			return cnx.getContent();
    		} catch (IOException e) {
    			// On stoppe si on a atteint le nombre max de recursion :
    			// Afin d'éviter des boucles infinis
    			if (maxcount<=0) {
    				throw e;
    			}
     
    			// On récupère l'URL de la connexion :
    			URL cnxUrl = cnx.getURL();
     
    			// On compare l'URL originale avec celle de la connexion :
    			if ( url.equals(cnxUrl) ) {
    				// Si c'est les mêmes, alors on remonte l'erreur :
    				throw e;
    			}
     
    			// Sinon cela signifie qu'on a eu une redirection
    			// qui a finalement générée une erreur.
    			// => On va alors tenter de réencoder l'URL :
    			URL newUrl = new URL(encode(cnxUrl.toString()));
     
    			// et on fait un appel récursif sur cette nouvelle URL :
    			return getContent(newUrl, maxcount-1);
    		}
    	}
    En clair : en cas d'erreur, on "traite" l'exception pour vérifier si l'URL de la connexion a changé, et si c'est le cas on tente de réencoder l'URL...



    a++

  6. #6
    Membre chevronné
    Avatar de ska_root
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    1 203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Service public

    Informations forums :
    Inscription : Août 2005
    Messages : 1 203
    Points : 1 839
    Points
    1 839
    Par défaut
    Merci pour ces précisions adiGuba

    Je te rejoins en ce qui concerne le fait que le serveur renvoie une URI non valide alors qu'il devrait la corriger. Malheureusement je n'ai pas la main sur le process de redirection des friendly's urls du serveur distant.

    J'ai donc bien pris conscience de la non-portabilité de mon code (d'où l'absence de test sur le code de response HTTP).
    idem pour setInstanceFollowRedirects(false) et idem pour l'encodage sauvage que je réalise uniquement sur la dernière bride du queryString d'ailleurs...

    Je retiens ta méthode sur les héxas pour les caractères réservés, c'est quand même 'achement plus propre...

    Je vais regarder de ce pas les libs jakarta, c'est vrai que je trouve "légères" les possibilités de la classe URL de Sun.

    En tout cas, merci pour ta réponse et l'énergie qu'elle t'a demandé...


+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Batch] Remplacer espaces par underscores dans noms de fichiers
    Par Ysae68 dans le forum Scripts/Batch
    Réponses: 13
    Dernier message: 28/08/2017, 16h56
  2. Petits pb en VBA :espace dans noms des fichiers
    Par Calimero33 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 02/07/2010, 22h23
  3. Problème espaces dans nom de fichier
    Par Mygush dans le forum Général Java
    Réponses: 9
    Dernier message: 31/10/2008, 12h21
  4. problème d'accent dans nom de fichier à récupérer
    Par Gunner4902 dans le forum Langage
    Réponses: 4
    Dernier message: 20/07/2008, 13h11
  5. Supprimer les espaces des noms de fichier
    Par Cathy dans le forum Linux
    Réponses: 20
    Dernier message: 04/08/2005, 17h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo