Transfert de fichiers via FTP en C++


Le téléchargement d'un fichier depuis le navigateur s'effectue par un simple clic de souris. L'opération de téléchargement est transparente. La seconde solution consiste à utiliser l'outil de commande ftp ; il faut utiliser les commandes OPEN, GET... Pour réaliser le rappatriement de plusieurs fichiers selon un critère de filtre, il est possible de réaliser un programme en mode console qui fait appel à l'API Win32 WinInet. Cette API comporte des fonctions pour utiliser le protocole de transfert de fichiers FTP. Voici la définition des fonctions InternetOpen, InternetConnect et FtpGetFile.
HINTERNET InternetOpen(
    LPCTSTR   lpszAgent,
    DWORD   dwAccessType,
    LPCTSTR   lpszProxyName,
    LPCTSTR   lpszProxyBypass,
    DWORD   dwFlags
);
HINTERNET InternetConnect(
    HINTERNET   hInternet,
    LPCTSTR   lpszServerName,
    INTERNET_PORT   nServerPort,
    LPCTSTR   lpszUserName,
    LPCTSTR   lpszPassword,
    DWORD   dwService,
    DWORD   dwFlags,
    DWORD_PTR   dwContext
);
BOOL FtpGetFile(
    HINTERNET  hConnect,
    LPCTSTR  lpszRemoteFile,
    LPCTSTR  lpszNewFile,
    BOOL  fFailIfExists,
    DWORD  dwFlagsAndAttributes,
    DWORD  dwFlags,
    DWORD_PTR  dwContext
);
La fonction InternetOpen prépare l'application à utiliser l'API Win32 WinInet.
La fonction InternetConnect ouvre une session HTPP, FTP ou GOPHER sur un site donné. Le paramètre nServerPort a la veleur INTERNET_DEFAULT_FTP_PORT et le paramètre dwService a la valeur INTERNET_SERVICE_FTP, ainsi la session est de type FTP.
Une fois que la connexion est établie, on utilise l'API FtpSetCurrentDirectory pour se positionner dans un répertoire donné.
La recherche des fichiers à récupérer est assurée par un filtre qui est passé en paramètre à l'API FtpFindFirstFile. L'API InternetFindNextFile permet de passer au fichier suivant. Pour chaque fichier détecté, on appel l'API FtpGetFile pour le récupérer.
#include "stdafx.h"
#include "windows.h"
#include "wininet.h"
#include "stdio.h"
#include "stdlib.h"
#pragma comment(lib, "wininet.lib")

#define SERVERNAME		"pex18"
#define USERNAME		"bill"
#define USERPWD			"billpwd"
#define SRC_DIRECTORY	"/maia/maia_app/DECADE/referentiel"
#define DEST_DIRECTORY	"D:\\Dev\\FTP\\FTP_FILES"
#define FILENAME		"*.ZIP"

char g_szServer[255];
char g_szUser[255];
char g_szPwd[255];
char g_szSourceDir[255];
char g_szDestDir[255];
char g_szCmd[255];
char g_szFileName[255];

void main(int argc, char* argv[])
{
	HINTERNET hInternetSession;          // handle to internet connection
	HINTERNET hFTPSession;               // handle to FTP session
	HINTERNET hFileConnection;           // handle to file enumeration
	WIN32_FIND_DATA sFindData;           // structure to hold FIND data
	BOOL bResult = TRUE;                 // Boolean for return code

	hInternetSession = InternetOpen(
					  "Microsoft Internet Explorer",     // agent
					  INTERNET_OPEN_TYPE_DIRECT,          // access
					  NULL,                          // proxy server
					  NULL,                              // defaults
					  0);                                // synchronous

	if( hInternetSession == NULL )
	{
		printf("InternetOpen failed\nGetLastError()=%ld\n", GetLastError());
		exit(1);
		return;
	}

	strcpy(g_szServer, SERVERNAME);
	strcpy(g_szUser, USERNAME);
	strcpy(g_szPwd, USERPWD);

	hFTPSession = ::InternetConnect(
			 hInternetSession,					// Handle from a previous call to InternetOpen.
			 g_szServer,						// Server we want to connect to
			 INTERNET_DEFAULT_FTP_PORT,			// Use appropriate port.
			 g_szUser,                          // Use anonymous for username.
			 g_szPwd,                           // Use e-mail name for password
			 INTERNET_SERVICE_FTP,				// Flag to use FTP services
			 0,									// Flags (see SDK docs)
			 0);								// Synchronous mode

	if( hFTPSession == NULL )
	{
		printf("InternetConnect failed\nGetLastError()=%ld\n", GetLastError());
		InternetCloseHandle(hInternetSession);
		exit(1);
		return;
	}

	strcpy(g_szSourceDir, SRC_DIRECTORY);

	bResult = ::FtpSetCurrentDirectory(hFTPSession, g_szSourceDir);
	if( bResult == FALSE )
	{
		printf("FtpSetCurrentDirectory failed\nGetLastError()=%ld\n", GetLastError());
		InternetCloseHandle(hFTPSession);
		InternetCloseHandle(hInternetSession);
		exit(1);
		return;
	}

	strcpy(g_szDestDir, DEST_DIRECTORY);
	strcpy(g_szFileName, FILENAME);

	hFileConnection = ::FtpFindFirstFile(hFTPSession, g_szFileName, &sFindData, 0, 0);
	if (hFileConnection != (HINTERNET)NULL)
	{

		while (bResult)
		{
			char szInputFile[1024];
			sprintf(szInputFile, "%s", sFindData.cFileName);
			char szOutputFile[1024];
			sprintf(szOutputFile, "%s%s", g_szDestDir, sFindData.cFileName);
			printf("GET <%s> To <%s>\n", szInputFile, szOutputFile);

			// Transfer the file.
			bResult = ::FtpGetFile(hFTPSession, szInputFile, szOutputFile, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 0);
			if( bResult )
				printf("FtpGetFile OK\n");
			else
				printf("FtpGetFile failed\n");

			// Get next file.
			bResult = ::InternetFindNextFile(hFileConnection, &sFindData);
		}
	}

	// Close connections.
	InternetCloseHandle(hFileConnection);
	InternetCloseHandle(hFTPSession);
	InternetCloseHandle(hInternetSession);

	exit(0);
	return;
}

 
© 2001 Christophe Pichaud. All rights reserved.