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

Java Discussion :

Client FTP en Java


Sujet :

Java

  1. #1
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut Client FTP en Java
    Bonjour,

    J'écris un client FTP en Java à partir de l'API FTPConnection. J'ai créé la méthode ls qui exécute la commande "LIST" sur le serveur FTP (TYPSoft). Cette méthode peut prendre en argument le chemin d'un répertoire. Dans ce cas, la méthode exécute la commande "LIST "+cheminDuRepertoire. Mais le serveur ne me retourne que la description de ce répertoire :

    drw-rw-rw- 1 ftp ftp 0 May 22 13:58 DL

    au lieu de lister son contenu. Je ne sais pas si le problème vient du code Java ou de la commande en elle-même. Pour ce qui est de la commande, j'ai vérifié sur le Net et je ne pense pas qu'il puisse y avoir une erreur, c'est plutôt trivial. Le chemin est passé en absolu, mais ça m'étonnerait que l'erreur vienne de là.

    Avant de commencer à poster du code, puisqu'il y en a quand même pas mal, je voudrais savoir si quelqu'un a déjà entendu parler de ce genre de problème.

  2. #2
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Par défaut
    Ton serveur ftp est peut-être protégé contre le listage des répertoires.

    As-tu essayé ta commande directement dans une console pour voir ce que te répondait le serveur?

    Sinon, tu as déjà un client FTP bien fait et libre qui existe: va voir du côté de l'API commons-net de Jakarta: inutile de réinventer la roue quand on peut s'en passer
    Avant de poster, pensez à regarder la FAQ, les tutoriaux, la Javadoc (de la JRE que vous utilisez) et à faire une recherche
    Je ne réponds pas aux questions techniques par MP: les forums sont faits pour ça
    Mes articles et tutoriaux & Mon blog informatique

  3. #3
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    Je vais tester la commande comme tu me le conseilles.

    Sinon, je suis obligé de réaliser ce client, il s'agit d'une demande de mon tuteur de stage. :-p

  4. #4
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    Bon, j'ai essayé en ligne de commande, et le problème vient du serveur (TYPSoft 1.11). Il ne permet pas de lister un répertoire entré en argument de la commande LIST (ou ls). Par contre, LIST seule fonctionne correctement.

    Je crois que ce sujet peut être déplacé vers un autre forum.

  5. #5
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    J'ai une nouvelle question !

    Maintenant, je me creuse la tête pour trouver un moyen de tester, toujours en Java et pour le protocole FTP, si un chemin donné mène vers un répertoire ou non (en gros tester l'existence d'un répertoire à partir de son chemin). Attention, il doit s'agir d'un répertoire uniquement, si le chemin mène à un fichier, le résultat doit être false.

    Avez-vous une idée ?

    J'ai déjà essayé de récupérer des informations sur le chemin avec LIST (et voir si l'entête est "d"), mais bien sûr, s'il s'agit d'un répertoire, c'est son contenu qui est listé ! -_-'

  6. #6
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Par défaut
    Tu te déplaces un niveau en dessous et tu effectues un LIST.

    Là, si le nom recherché n'apparaît pas dans la liste, false

    Si le nom existe, tu regardes le début de la ligne:
    "drw-rw-rw- ..."

    Si ta ligne commence par un d, c'est un répertoire
    Sinon, c'est un fichier

    Exremple: si tu veux tester si /toto/titi est un répertoire, tu effectues ton "LIST" dans le répertoire /toto, et tu regardes la ligne correspondant à titi
    Avant de poster, pensez à regarder la FAQ, les tutoriaux, la Javadoc (de la JRE que vous utilisez) et à faire une recherche
    Je ne réponds pas aux questions techniques par MP: les forums sont faits pour ça
    Mes articles et tutoriaux & Mon blog informatique

  7. #7
    Membre éprouvé
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Par défaut
    Sinon tout simplement, tu lance un CWD sur le chemin demandé.
    Deux cas :
    1. Ca fonctionne : Tu as un code de retour de type 2xx (généralement 250)
    2. Ca ne fonctionne pas : Tu as un code de retour de type 5xx (généralement 550)


    Il suffit de regarder le code de retour de ton ftp. 2xx ---> true, 5xx ---> false

    Cordialement

    Fred

  8. #8
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    Tu te déplaces un niveau en dessous et tu effectues un LIST.

    Là, si le nom recherché n'apparaît pas dans la liste, false

    Si le nom existe, tu regardes le début de la ligne:
    "drw-rw-rw- ..."

    Si ta ligne commence par un d, c'est un répertoire
    Sinon, c'est un fichier

    Exremple: si tu veux tester si /toto/titi est un répertoire, tu effectues ton "LIST" dans le répertoire /toto, et tu regardes la ligne correspondant à titi
    J'y ai pensé, mais ça ne fonctionne pas. Le problème, c'est que si j'utilise ".." en fin du PATH du répertoire intéressé, alors je n'ai pas le nom du répertoire, et je ne peux donc pas le rechercher dans la liste.

    Mais c'est bien vu, j'avoue que lorsque ça m'est venu en tête, j'y ai vraiment cru !

    Je vais essayer la solution de Fred (moi aussi je m'appelle Fred).



    Edit : j'y pense ! Si j'exécute la commande CWD, alors je vais changer de répertoire de travail, et ce n'est pas non plus le but recherché. Non ?

    Edit2 : j'ai une nouvelle idée. J'écris le chemin du répertoire de manière absolue. Chaque nom du chemin (séparé par "/" du suivant donc) est placé dans un tableau ou un vecteur, dans l'ordre d'apparition. Si le tableau contient "..", alors je supprime cette entrée et la précédente (ce qui revient à remonter d'un répertoire). Au final, le PATH devrait être nettoyé de tous les "..", et je pourrai appliquer la méthode du LIST sur le répertoire parent.

    Je vais essayer ça mais continuez à proposer vos idées !

  9. #9
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    J'ai trouvé ! Voilà les méthodes :

    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
    public boolean isRemoteDirectory(final String path) throws Exception {
    		if(!existsRemotely(path)) return false;
    		response=executeCommand("size "+path);
    		if(isPositiveCompleteResponse(response)) return false;
    		response=executeCommand("mdtm "+path);
    		if(isPositiveCompleteResponse(response)) return true;
    		response=executeCommand("retr "+path);
    		return !isPositiveCompleteResponse(response);
    	}
     
     
    	public boolean existsRemotely(final String path) throws Exception {
    		response=executeCommand("size "+path);
    		if(isPositiveCompleteResponse(response)) return true;
    		response=executeCommand("mdtm "+path);
    		if(isPositiveCompleteResponse(response)) return true;
    		response=executeCommand("retr "+path);
    		return isPositivePreliminaryResponse(response)||
    				isPositiveCompleteResponse(response)||
    				isTransientNegativeResponse(response);
    	}
    executeCommand exécute la commande et renvoie la réponse du serveur sous forme d'entier.

    Les méthodes d'interprétation des réponses :

    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
    private boolean isPositivePreliminaryResponse(final int response) {
    		return response>=100&&response<200;
    	}
     
     
    	private boolean isPositiveCompleteResponse(final int response) {
    		return response>=200&&response<300;
    	}
     
     
    	private boolean isPositiveIntermediateResponse(final int response) {
    		return response>=300&&response<400;
    	}
     
     
    	private boolean isTransientNegativeResponse(int response) {
    		return (response>=400 && response<500);
    	}

  10. #10
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    Nouveau problème. Je voudrais réaliser un pourcentage de progression pour l'upload et le téléchargement (toujours en FTP), mais je ne sais absolument pas comment m'y prendre. Mon client étant entièrement en lignes de commande, pas question d'utiliser ProgressMonitor. Avez-vous des suggestions ?

  11. #11
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Par défaut
    Avec un LIST, tu dois contrôler préalablement la taille du fichier à télécharger.

    Ensuite, lorsque tu télécharges, tu utilises certainement un "Stream" que tu lis morceaux par morceaux (en général en bouclant avec un tableau de 1024 bytes). Il te suffit de faire le rapport entre le nombre d'octets réellement passés dans ton Stream à chaque boucle et la taille globale.

    Evidemment, c'est le même principe en upload.
    Avant de poster, pensez à regarder la FAQ, les tutoriaux, la Javadoc (de la JRE que vous utilisez) et à faire une recherche
    Je ne réponds pas aux questions techniques par MP: les forums sont faits pour ça
    Mes articles et tutoriaux & Mon blog informatique

  12. #12
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    Je ne suis pas sûr que ta solution soit valable dans mon cas, car je ne t'ai pas tout dit. En fait, mes méthodes de téléchargement (et d'upload cela va de soi) peuvent prendre en paramètre un dossier, et pas seulement un fichier. Dans le cas d'un répertoire, la méthode le parcourt récursivement pour recréer toute la hiérarchie de sous-répertoires et télécharger et placer tous les fichiers au bon endroit.

    Or - j'en viens au fait - le pourcentage qui m'intéresse est celui global, c'est-à-dire, dans le cas du téléchargement d'un répertoire, le ratio quantité téléchargé/taille totale. Or la taille d'un répertoire par les commandes FTP est zéro, il me faudrait donc connaître à l'avance la taille de toute son arborescence (ce qui peut se réaliser plutôt facilement à vrai dire). Le problème, c'est pour connaître la quantité téléchargée, car comme expliqué précédemment, cela se fait récursivement. Je ne sais pas si je suis assez clair. Voilà les méthodes pour le téléchargement :

    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
     
    	public void get(String remotePath,String localPath) throws Exception {
    		String fileName=remoteFileName(remotePath);
    		remotePath=remoteAbsolutePath(remotePath);
    		localPath=localAbsolutePath(localPath);
    		if(isLocalDirectory(localPath)) localPath+=File.separator+fileName;
    		if(!existsRemotely(remotePath)) throw new Exception(remotePath+": No such file or directory");
    		else if(isRemoteDirectory(remotePath)) _getDirectory(remotePath,localPath);
    		else _get(remotePath,localPath);
    	}
     
     
    	abstract void _get(String remotePath,String localPath) throws Exception;
     
     
    	void _getDirectory(final String remotePath,final String localPath) throws Exception {
    		String newRemotePath,newLocalPath;
    		int i;
    		if(!isLocalDirectory(localPath)) _lmkdir(localPath);
    		final String[] list=_list(remotePath);
    		for(i=0;i<list.length;i++) if(!(list[i].equals(".")||list[i].equals(".."))) {
    			newRemotePath=remotePath+"/"+list[i];
    			newLocalPath=localPath+File.separator+list[i];
    			if(isRemoteDirectory(newRemotePath)) _getDirectory(newRemotePath,newLocalPath);
    			else _get(newRemotePath,newLocalPath);
    		}
    	}
    La méthode get est celle appelée en externe. _get sert au téléchargement de fichiers (en abstract car redéfinie en fonction du protocole). _getRepertory sert évidemment au téléchargement des dossiers.

    J'ai donc eu une nouvelle idée, mais je ne sais ni s'il est possible de la mettre en oeuvre, ni comment. Il s'agirait de lancer un thread connaissant la taille totale à télécharger, et scannant régulièrement le débit du serveur FTP. Ainsi il suffit d'appliquer un bête calcul temps écoulé x débit / taille totale pour avoir le pourcentage (enfin c'est plus subtil car à chaque changement de débit il faut ajouter le transfert qui a eu lieu sur l'intervalle de temps courant, et lui ajouter la taille déjà téléchargée qui est enregistrée par le thread, mais ce ne sont que des mathématiques).

    Donc est-ce possible de connaître le débit d'un serveur FTP avec du Java ?

  13. #13
    Membre éprouvé
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Par défaut
    Sinon pourquoi ne pas le faire dirrectement dans _get ?

    Je suppose qu'à un endroit ou à un autre, tu dois faire la methode classique des tableaux de bits et je suppose que c'est dans _get, donc il suffit de modifier cette fonction pour y afficher l'avancement d'une facon ou d'une autre...

    Fred

  14. #14
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    Je vais essayer de le faire dans _get, mais cela m'aurait tout de même intéressé de savoir si on pouvait connaître le débit d'un serveur FTP avec du Java.

  15. #15
    Membre éprouvé
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Par défaut
    Bah ce qu'on appelle le débit c'est le nombre de bits que tu transfert à la seconde, et à part en regardant combien de tableaux de x bytes tu transfert en une seconde je vois pas trop comment faire

    Fred

  16. #16
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Par défaut
    Bah il suffit de la calculer en direct avec un Timer.

    Quand tu reçois tes informations (un nouveau tableau de 1024 bytes dans ta boucle par exemple), tu effectues un "System.currentTimeMillis()", et par une règle de trois élémentaire, tu en déduis ton débit (en ayant sauvegardé la valeur précédente de ton "currentTime", évidemment).

    Ensuite, je pense que calculer le % réel de transfert à chaque passage est plus fiable qu'un "débit * temps".

    Enfin, je ne vois pas ce qui t'empêche de faire ta barre de progression globale.
    Il n'est effectivement pas dur de connaître la taille totale de ce que tu veux télécharger, ni de connaître le volume total d'informations réellement transférées (avec une variable de classe à l'extérieur de ta méthode _get() que tu incrémente à chaque passage dans la boucle).

    Evidemment, il ne faut pas remettre à zéro cette variable de classe au prochain fichier téléchargé si tu télécharges un répertoire entier. A mon avis, pour ça, il te suffit de passer un booléen à ta méthode "_get", pour indiquer si tu télécharges un répertoire entier ou un fichier isolé
    Avant de poster, pensez à regarder la FAQ, les tutoriaux, la Javadoc (de la JRE que vous utilisez) et à faire une recherche
    Je ne réponds pas aux questions techniques par MP: les forums sont faits pour ça
    Mes articles et tutoriaux & Mon blog informatique

  17. #17
    Membre averti
    Inscrit en
    Août 2006
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 29
    Par défaut
    C'est vrai, maintenant que j'y réfléchis, c'est un peu absurde ma proposition.

    J'ai mis en place ta méthode.


    Edit : pour ce qui est de la méthode "_get", elle n'accepte que des fichiers. C'est "get", sans tiret bas, qui fait le tri, et qui sert de méthode d'accueil (c'est peut-être bizarre mais c'est ma manière de programmer ).

Discussions similaires

  1. Client FTP en Java
    Par farid754 dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 21/06/2011, 00h51
  2. Serveur / Client FTP Java
    Par Benj' dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 02/03/2010, 15h13
  3. Client FTP JAVA
    Par jyms2006 dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 16/10/2008, 14h14
  4. Java Client FTP
    Par ®om dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 04/09/2006, 10h17
  5. [Débutant(e)] cherche client FTP en java
    Par javac*.java dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 02/02/2006, 11h31

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