Télécharger un fichier à partir du serveur FTP en Java

En utilisant  l'API Apache Commons Net, il est facile de coder un programme pour le téléchargement d'un fichier à partir d'un serveur FTP. Dans cet article, vous allez apprendre comment implémenter correctement le code java pour télécharger des fichiers à partir du serveur via le protocole FTP.

L'API Apache Commons Net et le Téléchargement FTP

La classe org.apache.commons.net.ftp.FTPClient fournit deux méthodes pour télécharger des fichiers à partir du serveur FTP:

1) boolean retrieveFile(String remote, OutputStream local): cette méthode récupère le fichier sur le serveur en spécifiant son chemin dans le paramètre remote, et écrit les octets récupérés en utilisant un OutputStream. Cette méthode retourne true si l'opération a été accomplie avec succès, sinon false. Cette méthode est adaptée avec notre programme quand on a pas besoin de connaitre les informations sur le transfert et comment le fichier est enregistré sur disque. à la fin du transfert, on doit fermer le flux de sortie OutputStream à la fin du téléchargement.

2) InputStream retrieveFileStream(String remote): cette méthode prend seulement comme paramètre le chemin du fichier distant et n'a pas besoin d'un OutputStream, par contre elle retourne un InputStream qui peut être utile pour lire les octets reçus du fichier. Cette méthode nous donne plus de contrôle sur la manière dont les octets sont écrits sur le disque local. Il y a deux points importants sur l'utilisation de cette méthode:
  • La méthode completePendingCommand() doit être appelée pour finaliser le transfert et vérifier la valeur retournée pour voir si le téléchargement a bien eu lieu.
  • On doit fermer le flux de lecture InputStream.
La question est quelle méthode doit-on utiliser? Voici quelques astuces:
  • La première méthode est la plus simple pour télécharger un fichier distant en passant un argument OutputStream du fichier qu'on veut sauvegarder sur disque.
  • La deuxième méthode nous donne plus de contrôle sur la manière dont le transfert est effectué, donc elle requit plus code à écrire en créant un InputStream pour lire les octets reçus et un OutputStream  pour sauvegarder les octets lus. Cette méthode est utile si on veut connaitre combien d'octets ont été transférés et combien il reste. La méthode completePendingCommand() doit être appeler pour terminer le téléchargement.
  • Les deux méthodes déclenchent une exception IOException ou l'une de ces deux exceptions: FTPConnectionClosedExcception et CopyStreamException. Par conséquent assurez-vous de bien gérer ces exceptions quand vous invoquez les méthodes.
En addition, les deux méthodes suivantes doivent être appelées avant l'appel des méthodes retrieveFile() et retrieveFileStream():

- void enterLocalPassiveMode(): cette méthode change le mode de connexion à partir du mode serveur-vers-client en client-vers-serveur, ce qui veut éviter le problème d'interdiction de firewall.

- void setFileType(int fileType): cette méthode modifie le type de fichier a transférer, il est recommandé de changer le type en FTP.BINARY_FILE_TYPE, plutôt que FTP.ASCII_FILE_TYPE même si c'est un fichier texte.

Les étapes pour télécharger un fichier en Java

Voici les étapes pour implémenter correctement le code de téléchargement (download) d'un fichier distant à partir du serveur FTP en utilisant l'API Apache Commons Net:
  • Se connecter et s'identifier au serveur.
  • Utiliser le mode de connexion passive.
  • Modifier le type de transfert en binaire.
  • Créer un outputStream pour sauvegarder le fichier téléchargé en disque.
  • Préciser le chemin d'enregistrement sur le disque.
  • Si vous utilisez la méthode retriveFile():
    • Passer outputStream et le chemin du fichier comme arguments.
    • Fermer le flux d'écriture outputStream.
    • Lire la valeur renvoyée pour vérifier si le download a réussi.
  • Si vous utilisez la méthode retriveFileStream():
    • Récupérer le InputStream retourné par la méthode retriveFileStream().
    • Créer un tableau d'octets (buffer) d'une taille définie (généralement 4096) pour lire les octets et les écrire avec un outputStream.
    • Appeler la méthode completePendingCommand() pour finaliser le transfert et vérifier la valeur retournée pour voir si le transfert a réussi.
    • Fermer les flux de lecture et d'écriture InputStream et outputStream.
  • Se déconnecter du serveur avec la méthode disconnect().

    Programme de téléchargement d'un fichier avec FTP en Java

    Ce code montre comment télécharger un fichier à partir du serveur FTP en utilisant ces deux méthodes:
    • boolean retrieveFile(String remote, InputStream local)
    • inputStream retrieveFileStream(String remote)
    Voici le code complet:

    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import org.apache.commons.net.ftp.FTP;
    import org.apache.commons.net.ftp.FTPClient;
    import org.apache.commons.net.ftp.FTPFile;

    public class FTPDownloadFile {

    public static void main(String[] args) {
    String serveur = "AdresseDuServeur";
    int port = 21;
    String username = "VotreNomUtilisateur";
    String password = "votreMotDePasse";

    FTPClient ftpClient = new FTPClient();
    try {

    ftpClient.connect(serveur, port);
    ftpClient.login(username, password );
    ftpClient.enterLocalPassiveMode();

    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

    // Approche 1: téléchargement d'un fichier en utilisant InputStream
    File file = new File("plugins et styles.txt");

    String nomFichier = "plugins et styles.txt";
    InputStream inputStream = new FileInputStream(file);

    System.out.println("Début du téléchargement");
    //résultat du téléchargement
    boolean res = ftpClient.storeFile(nomFichier, inputStream);
    //fermer le flut de lecture
    inputStream.close();

    if (res==true) {
    System.out.println("Le fichier "+nomFichier+
    " a été téléchargé avec succès");
    }

    // Approche 2: téléchargement d'un fichier en utilisant OutputStream
    String nomFichier2 = "Piste 2.mp3";
    String CheminFichierDistant = "/songs/"+nomFichier2;
    File fichierlocal = new File("C:/Piste 2.mp3");

    // lister le dossier ou se trouve le fichier et
    // puis le rechercher avec le nom pour obtenir
    // sa taille qui va etre utilisée pour calculer
    // le ratio du téléchargement
    FTPFile[] files1 = ftpClient.listFiles("/songs");
    long size = 0;
    for(int i = 0;i<files1.length;i++){
    if(files1[i].getName().equals(nomFichier2))
    //obtenir la taille du fichier
    size = files1[i].getSize();
    }

    OutputStream outputStream2 = new BufferedOutputStream(
    new FileOutputStream(fichierlocal));
    InputStream inputStream2 = ftpClient.retrieveFileStream(
    CheminFichierDistant);

    byte[] bytesArray = new byte[4096];
    int bytesRead = -1;
    //tant qu'on a pas atteint la fin
    int transferé = 0;
    int pourcentage = 0;
    while ((bytesRead = inputStream2.read(bytesArray)) != -1) {
    //on écrit les octets dans l'emplacement précisé
    outputStream2.write(bytesArray, 0, bytesRead);
    transferé += bytesRead;
    pourcentage = (int) (transferé*100/size);
    System.out.println(pourcentage+"%");
    }
    //fermer les flux de lecture de d'écriture
    inputStream2.close();
    outputStream2.close();

    //résultat d
    res = ftpClient.completePendingCommand();
    if (res) {
    System.out.println("Le fichier "+nomFichier2+
    " a été téléchargé avec succès");
    }

    } catch (IOException e) {
    System.out.println(e.getMessage());
    e.printStackTrace();
    } finally {
    try {
    if (ftpClient.isConnected()) {
    //fermer la connexion FTP
    ftpClient.logout();
    ftpClient.disconnect();
    }
    } catch (IOException ex) {
    ex.printStackTrace();
    }
    }
    }
    }
    L'exécution de ce code indique que le download a été bien accompli:

    Début du téléchargement
    Le fichier plugins et styles.txt a été téléchargé avec succès
    Début du téléchargement
    1%
    2%
    3%
    .
    .
    98%
    99%
    99%
    100%
    Le fichier Piste 2.mp3 a été téléchargé avec succès