Outils pour utilisateurs

Outils du site


telechargements_simples_ftp

Téléchargements ftp simples (download / upload)

Objectif

Définir des fonctions simples pour coder des téléchargements ftp dans les 2 sens (download / upload) en utilisant le module Python 'ftplib'

Ouverture / fermeture de connexion et de session

import ftplib
 
def connexionftp(adresseftp, nom='anonymous', mdpasse='anonymous@', passif=True):
    """connexion au serveur ftp et ouverture de la session
       - adresseftp: adresse du serveur ftp
       - nom: nom de l'utilisateur enregistré ('anonymous' par défaut)
       - mdpasse: mot de passe de l'utilisateur ('anonymous@' par défaut)
       - passif: active ou désactive le mode passif (True par défaut)
       retourne la variable 'ftplib.FTP' après connexion et ouverture de session
    """
    ftp = ftplib.FTP()
    ftp.connect(adresseftp)
    ftp.login(nom, mdpasse)
    ftp.set_pasv(passif)
    return ftp

Pour fermer la connexion, il y a 2 méthodes:

  • ftp.quit(): fermeture 'polie' qui interagit avec le serveur
  • ftp.close(): fermeture unilatérale

En fait, on pourrait proposer:

def fermerftp(ftp):
    """ferme la connexion ftp
       - ftp: variable 'ftplib.FTP' sur une connexion ouverte
    """
    try:
        ftp.quit()
    except:
        ftp.close()    

Téléchargement d'un fichier serveur_ftp => disque_local (download)

def downloadftp(ftp, ficftp, repdsk='.', ficdsk=None):
    """télécharge le fichier ficftp du serv. ftp dans le rép. repdsk du disque
       - ftp: variable 'ftplib.FTP' sur une session ouverte
       - ficftp: nom du fichier ftp dans le répertoire courant
       - repdsk: répertoire du disque dans lequel il faut placer le fichier
       - ficdsk: si mentionné => c'est le nom qui sera utilisé sur disque
    """
    if ficdsk==None:
        ficdsk=ficftp
    with open(os.path.join(repdsk, ficdsk), 'wb') as f:
        ftp.retrbinary('RETR ' + ficftp, f.write)

Téléchargement d'un fichier disque_local => serveur_ftp (upload)

def uploadftp(ftp, ficdsk, ficftp=None):
    """télécharge le fichier ficdsk du disque dans le rép. courant du Serv. ftp
       - ftp: variable 'ftplib.FTP' sur une session ouverte
       - ficdsk: nom du fichier disque avec son chemin
       - ficftp: si mentionné => c'est le nom qui sera utilisé sur ftp
    """
    repdsk, ficdsk2 = os.path.split(ficdsk)
    if ficftp==None:
        ficftp = ficdsk2
    with open(ficdsk, "rb") as f:
        ftp.storbinary("STOR " + ficftp, f)

Actions diverses sur le serveur ftp

Connaître le répertoire courant sur le serveur ftp

repftp = ftp.pwd()

Changer de répertoire sur le serveur ftp

ftp.cwd(repftp)

Obtenir la liste du contenu d'un répertoire sur le serveur ftp

print ftp.nlst() => liste pour le répertoire courant
print ftp.nlst(repftp) => liste pour le répertoire repftp

Le problème de cette liste, c'est que les noms de sous-répertoires et les noms de fichiers sont retournés sans distinction, et qu'il n'y a pas de moyen simple de les distinguer.

Solution: passer par la méthode 'ftp.dir()'. Voilà comment on utilise cette méthode:

lignes = []
ftp.dir(repftp, lignes.append) # si repftp n'est pas cité: c'est le répertoire par défaut qui est pris
 
for ligne in lignes:
print ligne

Ce qui affiche (par exemple):

drwxrwsr-x   3 utilisateur site1396     4096 Apr 13 07:05 .
drwxrwsr-x   3 utilisateur site1396       24 Jan 12 12:08 ..
-rw-rw-r--   1 utilisateur site1396  2853888 Jan 17 14:43 basesql.db3
-rw-rw-r--   1 utilisateur site1396  2852784 Jan 17 15:07 basesql_sav1.db3
drwxrwsr-x   2 utilisateur site1396        6 Apr 12 10:46 repertoire
-rw-rw-r--   1 utilisateur site1396  2851325 Apr 13 07:06 basesql_sav2.db3

Remarque: les répertoires '.' et '..' ne sont renvoyés que pour les serveurs ftp sous Linux (pas sous Windows)

On a donc un moyen simple de savoir si un nom est un répertoire: si le 1er caractère de la ligne est 'd': c'est un répertoire. Sinon, c'est un fichier.

Voilà une fonction qui renvoie la liste des sous-répertoires, suivie de la liste des fichiers d'un répertoire donné du serveur ftp:

def listerepftp(ftp, repftp=None):
    """renvoie les noms de répertoires et de fichiers du répertoire sur ftp
       - ftp: variable 'ftplib.FTP' sur une session ouverte
       - repftp: répertoire sur ftp. Si absent => répertoire courant
       retourne la liste des sous-répertoires, suivie de la liste des fichiers
    """
    lignes, nomsfic, nomsrep = [], [], []
    if repftp==None:
        ftp.dir(lignes.append)
    else:
        ftp.dir(repftp, lignes.append)    
    for ligne in lignes:
        liste = ligne.split()
        if liste[0][0]=='d':
            nom = liste[-1]
            if nom!='.' and nom!='..':
                nomsrep.append(nom)
        else:
            nomsfic.append(liste[-1])
    return nomsrep, nomsfic

Utilisation: liste des répertoires et des fichiers du répertoire courant (reprise de l'exemple précédent):

repftps, ficftps = listerepftp(ftp)
 
print repftps
['repertoire']
 
print ficftps
['basesql.db3', 'basesql_sav1.db3', 'basesql_sav2.db3']
 
print 'basesql.db3' in ficftps
True

Connaitre la taille d'un fichier du serveur ftp.

Attention:

  • la méthode size n'est pas obligatoirement supportée par le serveur ftp.
  • il faut demander le passage au mode binaire pour éviter une erreur du genre “interdit en mode ASCII”.
# ficftp = fichier dont on veut connaître la taille
ftp.sendcmd('TYPE I') # passer en mode binaire (sinon, erreur avec size)
tailleftp = ftp.size(ficftp) # donne la taille en octets
if tailleftp != None:
    print tailleftp
else:    
    print "méthode 'ftp.size()' non supportée par le serveur ftp"   

Il y a d'autres méthodes courantes: créer / effacer un répertoire, renommer, etc… ⇒ Voir la doc.

On voit qu'avec ces différentes fonctions et méthodes, on pourrait facilement télécharger dans les 2 sens (download / upload) des arborescences de répertoires!


Amusez-vous bien!

telechargements_simples_ftp.txt · Dernière modification: 2012/04/14 10:22 de tyrtamos

Outils de la page