juillet
2014
De nos jours, il n’est pas rare d’échanger de l’information via le protocole FTP (File Transfert Protocol). Mais depuis l’affaire PRISM, l’accent est davantage mis sur la sécurité de ces échanges. S’il est facile de trouver des libraires permettant d’utiliser le protocole FTP et SFTP (SSH File Transfert Protocol), il l’est un peu moins d’en trouve une capable de faire du FTPS (File Transfert Protocol over SSL). Vu que je m’y suis heurté ces deux dernières semaines, je vous présentes mes « découvertes ».
Avant d’aller plus loin, il est bien sûr possible de faire tout cela directement avec le framework .NET (via l’espace de nom NET) mais cela serait assez fastidieux. Et puisque d’autres l’ont déjà fait pour nous, inutile de réinventer la roue.
Comme annoncé dans l’introduction, je me suis heurté au problème pendant quelques temps. Tentant d’abord d’utiliser directement le framework .NET., je me heurtais à une erreur me disant « Unable to connect to the remote server. ». Sans plus de détail, c’est un peu léger pour permettre le débogage. J’ai donc fouillé le net et après quelques essais avec des libraires diverses, je suis tombé sur System.Net.FtpClient. Une libraire qui m’a l’air assez bien faite et simple d’usage mais surtout, fonctionnelle !
Sans plus attendre, un peu de code avec, comme mise en situation, la récupération de fichiers au format CSV (pratiques pour l’échange de données d’une compagnie à une autre) depuis un serveur distant.
Premièrement (je devrais dire deuxièmement car il faut ajouter la dll aux références du projet en premier lieu), importons l’espace de nom histoire de pouvoir coder plus légèrement.
1 | Imports System.Net.FtpClient |
Et maintenant le vif du sujet, la récupération des fichiers. Voici la procédure. Nous la commenterons ensuite ligne par ligne.
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 34 35 36 37 38 | Private Sub GetCsvFiles() Try Dim ftps = New FtpClient ftps.Host = "ftps.LeServeurDistant.be" ftps.Credentials = New Net.NetworkCredential("username", "password") ftps.Port = 990 'port par defaut ftps.DataConnectionType = FtpDataConnectionType.PASVEX AddHandler ftps.ValidateCertificate, AddressOf OnValidateCertificate ftps.EncryptionMode = FtpEncryptionMode.Implicit For Each item In ftps.GetListing("le/chemin/des/fichiers/") If item.Type = FtpFileSystemObjectType.File Then If item.Name.EndsWith(".CSV") Then Console.Writeline("fichier en cours : " & item.FullName & ")" 'affichage du fichier en cours de traitement dans la console Dim reader As New IO.StreamReader(ftps.OpenRead(item.FullName), Text.Encoding.Default) Dim writer As New IO.StreamWriter(My.Settings.storageFolder & item.Name, False, Text.Encoding.Default) Dim line As String = reader.ReadLine While Not reader.EndOfStream writer.WriteLine(line) line = reader.ReadLine() End While writer.WriteLine(line) writer.Close() writer.Dispose() reader.Close() reader.Dispose() End If End If Next If ftps.IsConnected Then ftps.Disconnect() End If Catch ex As Exception Console.WriteLine(ex.Message) End Try End Sub |
Comme vous l’aurez remarqué, j’ai choisi d’utiliser un projet de type Application Console. En effet, pas besoin ici de jolis écrans. La console nous suffira pour afficher les infos utiles à suivre le bon déroulement du processus.
Décortiquons à présent ensemble cette procédure.
- Ligne 2 : Ouverture d’un bloc Try…Catch. Une bonne habitude à prendre, tout simplement.
- Lignes 3-6 : Création d’un objet FtpClient (que j’ai nommé ftps) auquel on assigne les valeurs qui vont bien aux propriétés habituelles que sont Host, Port et Credentials.
- Ligne 7 : Le type de connexion. Vous avez ici plusieurs possibilités. Dans mon cas, le serveur distant me renvoyant une adresse privée (192.168.X.X), il me fallait utilisé PASVEX.
- Ligne 9 : Ajout d’un gestionnaire d’événement pour la validation des certificats. J’y reviendrai après.
- Ligne 11 : Il s’agit ici de la raison pour laquelle nous faisons tout ça. C’est cette ligne qui définit le mode d’encryption des données. Avec le mode Implicit, les données sont cryptées de bout en bout. Avec le mode Explicit, l’encryption démarre après les politesses d’usages échangées avec le serveur.
- Ligne 13 : Démarrage d’une boucle qui va parcourir les éléments du répertoire (du serveur distant) passé en paramètre.
- Ligne 14 : Vérification que l’élément en cours est bien un fichier. Il pourrait s’agir d’un répertoire ou d’un lien symbolique.
- Lignes 15-30 : Ici, rien de bien spécifique. Si le fichier est bien un fichier CSV, on crée un stream de lecture et un stream d’écriture et on copie le fichier ligne par ligne en n’oubliant pas de libérer les ressources à la fin. Pour un autre format de fichier, cette méthode pourrait ne pas convenir. Notez également que j’utilise les paramètres de projet pour définir où stocker le fichier de notre côté.
- Lignes 32-34 : Si ce n’est pas déjà fait, fermeture de la connexion qui a été ouverte par la commande GetListing. On n’est jamais trop prudent.
- Lignes 35-37 : Affichage du message d’erreur éventuel.
Voilà pour ce qui est du code de la procédure. Revenons maintenant sur la validation des certificats. Car qui dit FTPS, dit certificats à accepter par celui qui se connecte au serveur distant (c’est-à-dire nous).
Dans mon cas, je n’ai pas fait la fine bouche. La récupération de ces données étant primordiales et la source digne de confiance, je les accepte quoi qu’il arrive. Voici ce que cela donne :
1 2 3 | Private Sub OnValidateCertificate(control As FtpClient, e As FtpSslValidationEventArgs) e.Accept = True End Sub |
Pour les plus pointilleux, les objets X509Certificates, 509Chain et SslPolicyErrors sont accessibles via la variable d’événement e. Libre à vous de gérer la validation des certificats comme bon vous semble. Personnellement, ce n’est pas ma tasse de thé et de loin.
Et voilà, il ne reste plus qu’à appeler cette procédure dans le main de notre projet et le tour est joué.
En espérant que cela en aidera plus d’un.
Kropernic.