CLIENT FTP AVEC L'API WINDOWS (WININET.DLL)

elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 - 31 août 2005 à 16:32
eclems Messages postés 104 Date d'inscription samedi 23 décembre 2000 Statut Membre Dernière intervention 9 mai 2013 - 12 oct. 2009 à 01:26
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/33543-client-ftp-avec-l-api-windows-wininet-dll

eclems Messages postés 104 Date d'inscription samedi 23 décembre 2000 Statut Membre Dernière intervention 9 mai 2013
12 oct. 2009 à 01:26
comment peut on faire pour connaitre la taille du serveur ftp avec cette librairie
merci encore et bravo
cs_francois04 Messages postés 1 Date d'inscription mercredi 27 février 2008 Statut Membre Dernière intervention 27 février 2008
27 févr. 2008 à 16:16
Je cherchais qqch de simple et pédagogique sur le sujet (ftp et delphi) :
c'est exactement ce qu'il me fallait !
Merci,
François
veki51 Messages postés 3 Date d'inscription vendredi 4 mai 2007 Statut Membre Dernière intervention 18 juin 2007
18 juin 2007 à 15:24
bonjour ton code est vraiment formidable merciiiiiiiiiiiii.
j'ai besoin de ton aide.

InternetOpen( PChar('Tiny FTP'), INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0 ); les paramètre de cette instruction je les pas compris.

STRUCT_DATA : _WIN32_FIND_DATAA; ???????????????
InternetConnect( PConnexionInternet, Pchar(Serveur), Port, Pchar(Login), Pchar(MotDePasse), INTERNET_SERVICE_FTP, 0, 0 ); les 3 paramètre qui son à la fin.

merci d'avance
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
17 mai 2007 à 14:31
Veki51 : Sois plus précis si tu as besoin d'aide pour faire fonctionner ces sources. Qu'est ce qui bloque au juste ?
Je voudrai pas être rabat-joie, mais le langage SMS ou phonétique, c'est pénible à lire...
veki51 Messages postés 3 Date d'inscription vendredi 4 mai 2007 Statut Membre Dernière intervention 18 juin 2007
17 mai 2007 à 13:26
merci boucoup pour ton code.mais ca marche pas avec moi??????
veki51 Messages postés 3 Date d'inscription vendredi 4 mai 2007 Statut Membre Dernière intervention 18 juin 2007
15 mai 2007 à 18:32
j'ai entraine d'aissai merci boucoup
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
13 mars 2007 à 21:34
Tout ce que je poste ici est entièrement libre, utilisable et modifiable par la communauté.

Vas y lache toi :-D
yomane51100 Messages postés 69 Date d'inscription jeudi 8 juin 2006 Statut Membre Dernière intervention 17 septembre 2010
13 mars 2007 à 18:37
bonjour a tous peut ton utiliser se programme en libre ou pa je nes pa besouin de faire des modif.
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
19 janv. 2007 à 18:11
Je n'ai pas trouvé le module ElgFTP, tu as livré que Module.pas avec ton projet TintyFTP. J'ai regardé dans le FTP.pas, il y a bien des commandes pour le répertoire mais pas celle là.

Peux t-être une j'ai mal lu ?

A tout a l'heure

Merci
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
19 janv. 2007 à 09:55
Tu peux acceder à un autre repertoire grace à "FtpSetCurrentDirectory".. j'ai du faire une fonction pour se ballader dans les dossier, regarde dans le module ElgFTP :-)
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
19 janv. 2007 à 04:24
Oui, J'ai mis un Application.ProcessMessages mais rien n'y fait.

Bon pour l'instant, ça fonctionne bien !

Je voulais savoir comment on peut atteindre directement un sous répertoire sur le serveur ?

Merci et à bientôt Damien

Phephelavi
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
18 janv. 2007 à 20:18
c'est pas normal, mon code plus haut ... le chemin du fichier est ecrit en dur et aprs l'avoir executé.. j'ai retouvé le fichier sur mon FTP.

As tu essayé de mettre un Application.ProcessMessages après l'upload ?

Je suis sur que c'est une connerie de rien du tout en plus ....
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
18 janv. 2007 à 18:19
Bonsoir Elguevel !

Je ne sais pas pourquoi cela ne veut pas fonctionner mais j'ai trouvé une solution.

J'ai beau mettre même en "dur" le chemin et le nom du fichier, après un envoi du fichier, il n'est toujours pas sur le serveur. Que je passe par un String ou un FileName, et même un OpenDialog.FileName, rien n'y fait !

Tous les exemples que j'ai trouvé sur les forums, c'est toujours une application avec envoi, suppression, téléchargement en passant par une boite de dialogue mais jamais en passant par des variables et par une tâche de fond.

Alors, j'ai posé un panel, unTDirectoyListBox relié à un TFileListBox et un composant OpenDialog. Je mets le panel en invisible pour par que l'utilisateur le voit !

Dans la procédure d'envoi, je place :
...
OpenDialog1.FileName := FileListBox1.Items[FileListBox1.ItemIndex];
+ ton code d'envoi du fichier
...

Et là, je n'ai plus de problème.

Si tu as une info sur le sujet, je suis preneur pour comprendre le problème pourquoi je suis obligé de passer par un TFileListBox pour que le nom du fichier soit bien compris et que le fichier soit placé sur le serveur.

Merci et bon weekend à toi et à tous les développeurs !

Phephelavi
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
17 janv. 2007 à 11:38
Je comprend pas parce qu'avec le code que je vous est fourni quelque poste plus haut, avec le nom de fichier ecrit en dur, çà passe sans probleme. et c'etait juste un probleme de "Sleep()" !

Reprenez le, et augmenté le temps de pause, et aller y au pas à pas ... franchement là je vois pas !

Sinon on peut aussi sniffer la trame qui passe pour voir ce qui se deroule réelement :-s mais bon ..
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
17 janv. 2007 à 09:46
Bonjour Damien,

J'ai fini l'intégration d'une gestion de procédure d'envoi FTP en suivant votre code mais je n'arrive toujours pas à envoyer le fichier sur le serveur.Dans l'exemple ci-dessous, j'ai repris votre premier code pour expliquer :

Voici une partie du code qui concerne l'envoi du fichier :

if OpenConnexion(Self.Handle, Serveur, Login, MotPasse, StrToInt(Port))
then begin
UpLoadFile(FichierLocal, ExtractFileName(FichierServeur));
Sleep(2000);
ShowMessage('Transfert réussi !');
...
end;

Dans ce cas, le fichier n'est pas mis sur le serveur (pas d'erreur, les variables contiennent bien les bonnes données)

Si je modifie le code comme ci-dessous :

if OpenConnexion(Self.Handle, Serveur, Login, MotPasse, StrToInt(Port))
then begin
if OpenDialog.Execute
then begin
OpenDialog.Title := 'CobraSecurite';
FichierLocal := OpenDialog.FileName;
UpLoadFile(FichierLocal, ExtractFileName(FichierServeur));
end;
Sleep(3000);
ShowMessage('Transfert réussi !');
end;

Là, ca marche, le fichier est sur le serveur. Je ne comprends pas pourquoi avec OpenDialog c'est OK, c'est au niveau de la chaine ? Je n'ai pas de routeur, juste le parefeu de Windows XP, un anti-virus, rien de plus conventionnel. Puis de toute façon, ca marche avec FTPExpert ou votre TinyFTP.

Mais l'envoi du fichier doit-être "transparent" pour l'utilisateur, il ne doit pas être obligé de passer par une boite de dialogue.

Merci encore pour aide, je continue...

Phephelavi
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
17 janv. 2007 à 08:43
Non aucun problème et pas de message d'erreur. Je peux envoyer le fichier en question avec ton programme TinyFTP, c'est OK sur le serveur mais quand j'interprète ton code dans mon programme, c'est comme s'il ne se passe rien.

Je continue à chercher et je vous contacterai

Oui, excusez moi, j'ai posté 2 fois

A+
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
16 janv. 2007 à 21:11
attention tu poste toujours deux fois :D

sinon n'a tu pas de probleme lié au reseau comme par exemple un firewall (ou anti virus genre norton) ou meme un routeur (meme si çà serai etonnant que çà vienne de là ) ?
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
16 janv. 2007 à 21:05
Encore moi Damien,

Voilà, j'ai modifié mon code, voici la procédure entière mais rien n'y fait, le fichier n'est toujours pas sur le serveur alors que la connexion et le transfert se sont bien déroulé (message de fin)

procedure TFCobraSAgent.EnvoyerFichierFTP;
//Se connecte au serveur et envoie le fichier de service de l'agent en cours

var
FichierLocal : string; //Nom du fichier en local Windows
FichierServeur : string; //Nom du fichier pour le serveur
Serveur : string; //Adresse serveur, ex : perso-ftp.wanadoo.fr
Login : string; //Nom utilisateur, ex : mr.martin@wanadoo.fr
MotPasse : string;
Port : string; //Le n° du port, FTP par défaut = 21
PConnexionInternet : HINTERNET;
PConnexionFTP : HINTERNET;

begin
//On récupère d'abord les paramètres du serveur (par un Reguitry
FCobraS.LireParamFTP(Serveur, Login, MotPasse, Port);
ShowMessage('Handle : ' + IntToStr(Self.Handle) + #13#10 +
'Adresse : ' + Serveur + #13#10 +
'Login : ' + Login + #13#10 +
'Mot de passe : ' + MotPasse + #13#10 +
'Port : ' + Port);

FichierLocal := 'C:\CobrasSecurite\MainCourante\CSmc.txt';
FichierServeur := 'CSmc.txt';

//Connexions : Internet, puis FTP
PConnexionInternet := InternetOpen(PChar('CobraSecurite'),
INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0);

if PConnexionInternet = nil
then Exit;

PConnexionFTP := InternetConnect(PConnexionInternet, Pchar(Serveur), StrToInt
(Port), Pchar(Login), Pchar(MotPasse), INTERNET_SERVICE_FTP, 0, 0 );

if PConnexionFTP = nil
then begin
InternetCloseHandle(PConnexionInternet);
Exit;
end;

//Envoi du fichier
Try
FtpPutFile(PConnexionFTP, PChar(FichierLocal), PChar(FichierServeur),
FTP_TRANSFER_TYPE_BINARY, 0);
Sleep(2000);
Finally
//On ferme la connexion
InternetCloseHandle(PConnexionInternet);
InternetCloseHandle(PConnexionFTP);
end;
ShowMessage('Transfert réussi !');
end;

Je n'ai pas d'erreur mais le fichier 'CSmc.txt' n'est toujours pas sur le serveur (je vérifie avec FTPExpert).

Merci pour votre réponse

Phephelavi
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
16 janv. 2007 à 19:31
Bonsoir Damien,

J'ai lu ton message, ExtractFolder est bien dans ton unité module.

Je vais modifié mon code et je vous tiens au courant demain.

Merci !
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
16 janv. 2007 à 10:19
J'ai trouvé la cause de ton probleme.

Le problème vient du fait qu'en utilisant mon programme tu declenche les evenements un par un.
Alors qu'en faisant tout d'un coup çà ne passe pas ... mais pourquoi ?
Tout simplement car a peine le fichier envoyé la connexion se termine trop vite.
Il faut simplement mettre une pause très courte après l'upload avant la fermeture des connexions.
PS : a la place de la pause il doit y avoir un systeme pour çà ; a voir.

Voila le bout de code:

var
FichierLocal : string;
FichierServeur : string;
Serveur : string;
Login : string;
MotPasse : string;

PConnexionInternet: HINTERNET;
PConnexionFTP : HINTERNET;

begin

FichierLocal := 'C:\Documents and Settings\leveugle\Bureau\test.txt';
FichierServeur := 'fichier.txt';

Serveur := 'serveurftp';
Login := 'login';
MotPasse:= 'motdepasse';


// Connexion
PConnexionInternet := InternetOpen( PChar('tralalala'), INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0 );

if PConnexionInternet = nil then Exit;

PConnexionFTP := InternetConnect( PConnexionInternet, Pchar(Serveur), 21, Pchar(Login), Pchar(MotPasse), INTERNET_SERVICE_FTP, 0, 0 );

if ( PConnexionFTP = nil ) then
begin
InternetCloseHandle( PConnexionInternet );
Exit;
end;

try
// Envoi le fichier "test.txt" vers le serveur sous le nom de "fichier.txt"
FtpPutFile( PConnexionFTP, PChar(FichierLocal), PChar(FichierServeur), FTP_TRANSFER_TYPE_BINARY, 0 );
Sleep( 2000 ); // Mettre une pause ici (cause de ton probleme)
finally
// On ferme la connexion
InternetCloseHandle(PConnexionInternet);
InternetCloseHandle(PConnexionFTP);
end;

end;
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
16 janv. 2007 à 09:45
Bonjour,

Suite à votre message de 09:12:34

Oui, j'ai bien indique le chemin complet du fichier :
C:\CobraS\Main\CSmc.txt.

Voilà le fichier qui est sur mon poste et je dois l'envoyer régulièrement à un serveur. ET j'ai vérifié les valuers des variables dans l'EDI Delphi, il m'indique bien :

avant extracFilename : C:\CobraS\Main\CSmc.txt
après extracFilename : CSmc.txt

Ma fonction est tout simple : juste envoyé ce fichier sur un serveur si tout. Sans OpenDialog, le fichier n'est pas placé sur le serveur : problème de chaine ? Au niveau des Slash / Qu'est-ce qui ferait que la même chaine formatée
n'aboutit pas dans mon code .

La manière doit être transparente pour l'utilisateur. Mon programme doit faire cet envoi sans que l'utilisateur intervienne.

Oui, j'utilise votre variable ailleurs pour être sûr que la connexion est coupée.

Merci pour aide !
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
16 janv. 2007 à 09:12
A quoi ressemble votre fonction ?
Avez vous indiqué un chemin complet ?
La variable IsConnected ne devrai plus vous servir, c'est juste une valeur utilisé par mon soft.
phephelavi Messages postés 40 Date d'inscription mardi 16 mai 2006 Statut Membre Dernière intervention 27 octobre 2009
16 janv. 2007 à 08:28
Bonjour,

J'ai pris connaissance de votre code et je l'ai "interprêté" pour l'intégrer dans un programme dont j'avais besoin d'une simple connexion et d'un envoi d'un fichier par session sur un serveur.

Voici le bout de code :

if OpenConnexion(Self.Handle, IServeur, IUtilisateur, ILogin, StrToInt(IPort))
then begin
IsConnected := true;
UpLoadFile(Fichier, ExtractFileName(Fichier));
...
end;

Tout se passe bien mais je rencontre un seul problème : le fichier n'est pas
mis sur le serveur, il est absent alors que la procédure a réussie. Pour
mieux comprendre le problème, j'ai repris un peu de votre code avec
Opendialog :

if OpenConnexion(Self.Handle, IServeur, IUtilisateur, ILogin, StrToInt(IPort))
then begin
IsConnected := true;
if OpenDialog.Execute
then begin
OpenDialog.Title := 'Uploader';
Fichier := OpenDialog.FileName;
UpLoadFile(Fichier, ExtractFileName(Fichier));
....
end;
end;
Et là, ca marche le fichier est sur le serveur ! Il y a bien un autre moyen de placer un fichier sans passer pas la boite de dialogue OpenDialog. Pourtant, j'ai vérifié le chemin du fichier ?

Avez-vous une suggestion ?

Merci d'avance

Phephelavi
exyacc Messages postés 163 Date d'inscription dimanche 20 octobre 2002 Statut Membre Dernière intervention 31 juillet 2008
20 nov. 2006 à 11:40
oki, merci
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
20 nov. 2006 à 11:04
oui en récupérant la taille du fichier avec "FtpGetFileSize" et en comparant avec ce qui est telechargé, je pense que l'affichage d'une barre de progression est possible.
exyacc Messages postés 163 Date d'inscription dimanche 20 octobre 2002 Statut Membre Dernière intervention 31 juillet 2008
20 nov. 2006 à 10:12
salut,
je voulais savoir s'il y avait moyen d'avoir une progression du telechargement ?
merci
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
10 août 2006 à 11:01
es tu sur que celà soit un problème de BitDefendeur... dans ce cas décoche FireWall, au moins t'es fixé !

A mon avis il doit y avoir un argument à changer pour que la connexion se fasse du client ... va voir la MSDN, ou alors dit moi sur quel serveur tu te connecte car je n'ai jamais eut ce problème !

A oui puis un autre truc tout con mais qui revient souvent ... As tu un routeur ou un modem routeur ?

++
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
10 août 2006 à 10:33
Je rencontre un soucis aussi bien avec ce prog qu'avec le client Indy FTP :
Au moment du tranfert de données, c'est le serveur qui établi la connexion pour les datas (donc connexion entrante) et BitDefender 9 pour ne citer que lui bloque ces connexions, même si on ajoute un règle qui autorise mon appli à accéder à internet (avec tout les droits possibles !)
J'ai testé avec FileZilla, ça ne se produit pas, FileZilla va établir la connexion de données lui-même, et n'attend pas que le serveur le fasse.
Nb : avec Indy j'ai testé les modes actif et passif, le comportement est quelque peu différent (N° de ports) mais il y a toujours ce pb de connexion entrante !
SISKODS9 Messages postés 6 Date d'inscription mardi 18 octobre 2005 Statut Membre Dernière intervention 19 septembre 2012
21 oct. 2005 à 06:38
Trés util dans mon cas, je ne connaissait pas Wininit.Dll, cela m'a permit d'integrer des fonctionnalités FTP dans la gestion des scripts de mon application (L'utilisateur peut écrire ses scripts lui-même).
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
21 sept. 2005 à 21:49
désolé je ne fait pas de .Net :-(

Par contre si tu as des questions à poser à propos de cette application, ou des améliorations à apporter n'hesite pas.

J'en ai pas mal chier pour le faire ce programme car l'API Wininet est très peu rependu ... la plupart préferant utiliser les composants Indy !

PS : J'ai fait une mise a jour pour ceux que çà interesse !

Damien.
slopes Messages postés 7 Date d'inscription mercredi 21 septembre 2005 Statut Membre Dernière intervention 9 janvier 2006
21 sept. 2005 à 15:11
oui, ton code m'interesse mais.... (il y a toujours un mais) je cherche à faire la même chose en .net.
J'ai réaliser une classe de connexion FTP, qui fonctionne trés bien sur un serveur FTP type UNIX, mais depuis que je suis sur un serveur FTP microsoft mon programme ne fonctionne plus, donc je me tourne vers les API windows pour trouver une solution :( et ton code va certainement m'aider...

merci
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
31 août 2005 à 16:32
Je vois que mon code n'interesse pas grand monde :s

Sinon j'ai repondu a ma question pour faire une recherche recursive qui permet de lister tout les fichiers d'un FTP :

{ Lit tout les fichier d'un serveur FTP en partant d'un chemin de depart ! }
procedure Recursive( tList : TListBox; Repertoire : string );
var
STRUCT_DATA : _WIN32_FIND_DATAA;
FoundFile : Pointer;
bFound : Boolean;
TypeFile : String;
Memorise : Array[0..50] of string;
idx : Integer;
i : Integer;
begin

// Init
i := 0;
idx := 0;
FoundFile := nil;
bFound := False;

if PConnexionFTP <> nil then
begin

FtpSetCurrentDirectory( PConnexionFTP, Pchar( SlachFTP(Repertoire) ) );
FoundFile := FtpFindFirstFile( PConnexionFTP, PChar('*.*'), STRUCT_DATA, 0, 0 );

if FoundFile <> nil then
repeat

if (STRUCT_DATA.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) = FILE_ATTRIBUTE_DIRECTORY then
begin
if ( Trim(STRUCT_DATA.cFileName) <> '.' ) and ( Trim(STRUCT_DATA.cFileName) <> '..' ) then
begin
Memorise[idx] := STRUCT_DATA.cFileName;
inc( idx );
end;
end else
begin

// TypeFile := AttributeToStr( STRUCT_DATA.dwFileAttributes );
tList.Items.Add( SlachFTP(GetCurrentDirectory( PConnexionFTP )) + STRUCT_DATA.cFileName );
end;

bFound := InternetFindNextFile( FoundFile, @STRUCT_DATA );

until not bFound;

InternetCloseHandle( FoundFile );
end;

for i := 0 to High( Memorise ) do
begin
if ( Memorise[i] <> '' ) then
begin
Recursive( tList, Memorise[i] );
FtpSetCurrentDirectory( PConnexionFTP, PChar( ExtractBeforeFolder( GetCurrentDirectory( PConnexionFTP ) ) ) );
Application.ProcessMessages;
end;
end;

end;

Voila ..

Damien
Rejoignez-nous