FTP ダウンロード :【VC++】




ブラウザでダウンロード
HTTP ダウンロード は、元々こちらがオリジナルで移植したものでした。
ですから、引数の処理はこちらのほうが手を抜いています
( スペースの処理が面倒なので ! で区切っています )

こちらでは、Wininet の仕様に沿ってプログレスバーの表示処理は、
コールバック関数内で行っています。
サブタイトル
以下は引数の指定方法です

ホスト名!リモートパス!ローカルパス!ユーザー!パスワード

例) localhost!/mysql51.exe!.\m.exe!lightbox!password

※ ダウンロードした後、そのディレクトリをエクスプローラで開きます
( カレントの場合は、.\ を付けないと表示されません )
#define _WIN32_WINNT 0x0500
#include <tchar.h>
#include "lightbox\lightbox.h"

#pragma comment( lib, "lightbox\\lightbox.lib" )
#pragma comment( lib, "shlwapi.lib" )
#pragma comment( lib, "wininet.lib" )   

#define IDD_FTPDOWNLOAD		129
#define IDC_TARGET			1000
#define IDC_FILEPATH		1001
#define IDC_PROGRESS1		1003
#define IDC_DOWNLOADSIZE	1005
#define THREAD_END			LBOX_USER + 1

LboxDlg *Dlg = NULL;
LboxProgressBar Pbar;
LboxThread Thread;
DWORD DataLen;
LboxToken Token;
LboxTool Tool;

// 文字列
LboxString LString;
LboxString Server;
LboxString RemoteFile;
LboxString LocalFile;
LboxString User;
LboxString Pass;

#define THREAD_END		LBOX_USER + 1

LRESULT CALLBACK DialogProc( HWND, UINT, WPARAM, LPARAM );
DWORD WINAPI ThreadProc( LPVOID lpParameter );

HINTERNET hSession;
HINTERNET hConnect;

DWORD nByte = 0;
BOOL bEnd = false;

// *********************************************************
// FtpGetFile のコールバック
// *********************************************************
void CALLBACK StatusFunc(
	HINTERNET hInternet,
	DWORD Context,
	DWORD Status,
	LPVOID StatusInfo,
	DWORD StatusInfoSize)
{
	if ( bEnd ) {
		InternetCloseHandle( hInternet );
		hInternet = NULL;
		return;
	}

	if ( Status == INTERNET_STATUS_RESPONSE_RECEIVED ) {
		nByte += *((DWORD *)StatusInfo);
		Pbar.SetPos( nByte );
	}
}

// *********************************************************
// Windows アプリケーションとしてのエントリポイント
// Link.exe で /SUBSYSTEM:WINDOWS がデフォルトで
// 指定される事になります
// *********************************************************
int APIENTRY WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow
)
{
	Token.CreateToken( lpCmdLine, "!" );
	Server = Token.Token[0];
	RemoteFile = Token.Token[1];
	LocalFile = Token.Token[2];
	User = Token.Token[3];
	Pass = Token.Token[4];

	DialogBox(
		hInstance,
		(LPCTSTR)IDD_FTPDOWNLOAD,
		GetDesktopWindow(),
		(DLGPROC)DialogProc);

	return 0;
}

// *********************************************************
// メッセージ処理
// *********************************************************
LRESULT CALLBACK DialogProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	switch( message ) {
		case WM_INITDIALOG:
			// ダイアログオブジェクトのインスタンス化
			Dlg = new LboxDlg( hDlg );
			// スタイル変更
			Dlg->ChangeStyle( WS_SYSMENU, 0 );
			Dlg->ChangeExStyle( WS_EX_APPWINDOW, 0 );
			Dlg->ChangeIcon( 107 );
			Dlg->StatusCreate( 0 );
			Dlg->StatusSetText( "ダウンロードしています。しばらくお待ち下さい" );

			LString = "ftp://";
			LString += Server;
			LString += RemoteFile;
			Dlg->EditSetText( IDC_TARGET, LString );

			Dlg->EditSetText( IDC_FILEPATH, LocalFile );

			// プログレスバーの初期化
			Pbar.hWnd = GetDlgItem( hDlg, IDC_PROGRESS1 );

			Thread.Create( hDlg, ThreadProc );

			return TRUE;

		case WM_COMMAND:
			if( LOWORD(wParam) == IDCANCEL ) 	{
				if ( Thread.hThread != NULL ) {
					Thread.Close();
				}
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;

		case THREAD_END:
			Thread.Close();
			EndDialog(hDlg, IDOK);

			// エクスプローラ起動用文字列作成
			LString = "explorer.exe /e,";
			LString += LocalFile;
			LString.RemoveFileSpec();
			// 起動
			Tool.Execute( LString, NULL );

			break;

	}
	return FALSE;
}

// *********************************************************
// ダウンロードスレッド
// *********************************************************
DWORD WINAPI ThreadProc( LPVOID lpParameter )
{

	hSession = InternetOpen(
		"lightbox",
		INTERNET_OPEN_TYPE_DIRECT,
		NULL, NULL, 0
	);
	if ( hSession == NULL ) {
		Dlg->PostMsg( THREAD_END, 0, 0 );
		return 0;
	}

	InternetSetStatusCallback( hSession, StatusFunc );

	hConnect = InternetConnect(
		hSession,
		Server.szLboxString,
		INTERNET_INVALID_PORT_NUMBER,
		User.szLboxString,
		Pass.szLboxString,
		INTERNET_SERVICE_FTP,
		INTERNET_FLAG_PASSIVE,
		NULL
	);
	if ( hConnect == NULL ) {
		InternetCloseHandle( hSession );
		Dlg->PostMsg( THREAD_END, 0, 0 );
		return 0;
	}

	WIN32_FIND_DATA wfd;

	FtpFindFirstFile(
		hConnect,
		RemoteFile.szLboxString,
		&wfd,
		INTERNET_FLAG_RELOAD,
		NULL
	);

	DataLen = wfd.nFileSizeLow;
	LboxString LWork;
	LWork.Printf( "%d", DataLen );
	LWork.NumberFormat();
	Dlg->EditSetText( IDC_DOWNLOADSIZE, LWork );
	Pbar.SetRange( 1, DataLen );
	Pbar.SetStep( 1 );

	BOOL bRet;

	bRet = FtpGetFile(
		hConnect,
		RemoteFile.szLboxString,
		LocalFile.szLboxString,
		false,
		FILE_ATTRIBUTE_NORMAL,
		FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD,
		1
	);

	if ( hSession != NULL ) {
		InternetCloseHandle( hConnect );
		InternetCloseHandle( hSession );
	}

	Dlg->PostMsg( THREAD_END, 0, 0 );
	return 0;
}