|
FTPクライアントを作る2
前回の続きでFTPクライアントを作っていきます。では早速コードを実装していきましょう。まずは"接続"ボタンが押されたときのイベントハンドラです。
// "接続"ボタン押下
void CFtpClientDlg::OnBnClickedBtnConnect()
{
int err = 0;
UpdateData();
OnBnClickedBtnDisconnect();
try
{
m_iSessionP = new CInternetSession;
m_ftpConP = m_iSessionP->GetFtpConnection
(m_xvEditServer, m_xvEditUser, m_xvEditPass,
INTERNET_INVALID_PORT_NUMBER, TRUE);
Refresh();
}
catch (CInternetException *eP)
{
eP->ReportError();
eP->Delete();
if (m_ftpConP) m_ftpConP = NULL;
if (m_iSessionP) {delete m_iSessionP; m_iSessionP = NULL;}
err = 1;
}
}
|
まずは、入力したサーバ名、ユーザ名、パスワードを読み取るためにUpdateData()関数を実行しておきます。また、現在接続中である場合は新しく接続する前に切断しておきます。そのため、OnBnClickedBtnDisconnect()を実行しておきます。
次は、前回に説明した通りに、CInternetSessionクラスのオブジェクトを作成し、GetFtpConnection()関数でサーバに接続し、CFtpConnectionクラスのオブジェクトを取得します。
CFtpConnection* CInternetSession::GetFtpConnection(
LPCTSTR pstrServer,
LPCTSTR pstrUserName = NULL,
LPCTSTR pstrPassword = NULL,
INTERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER,
BOOL bPassive = FALSE
); |
| 説明: |
FTPサーバへ接続し、CFtpConnectionクラスオブジェクトへのポインタを取得 |
| 引数: |
pstrServer:サーバ名
pstrUserName:ユーザ名。NULLの場合anonymousになる
pstrPassword:パスワード。NULLの場合anonymousであればユーザの電子メールアドレス、anonymousでなければ空白のパスワードになる
nPort:TCP/IPポート番号、指定しなければデフォルトポートが使われる
bPassive:PASSIVEモードで接続する場合TRUE、ACTIVEモードで接続する場合FALSE |
| 戻り値: |
CFtpConnectionクラスオブジェクトへのポインタ。エラーの場合はCInternetException例外をスローする。 |
GetFtpConnection()関数を呼ぶと、指定したサーバへ、指定したユーザ名、パスワードで接続されます。接続できなかった場合はCInternetExceptionの例外がスローされるので、catchブロックでエラー処理をします。これをやらないとエラー発生時にGetFtpConnection()から後の処理が飛ばされて関数を抜けてしまいますので、必ず例外処理をするようにしましょう。
FTPの転送モードはACTIVEモードとPASSIVEモードがあります。これはデータ転送のためのコネクションをサーバ側、クライアント側のどちらから張るかという違いがあります。詳しくは詳細に説明しているサイトがたくさんあるのでそちらを見てください。
接続が成功したら、ファイル一覧を取得して表示します。これは後で説明する自作のRefresh()関数でやっています。
次は"切断"ボタンが押されたときのイベントハンドラです。
// "切断"ボタン押下
void CFtpClientDlg::OnBnClickedBtnDisconnect()
{
UpdateData();
if (m_ftpConP) m_ftpConP = NULL;
if (m_iSessionP) {delete m_iSessionP; m_iSessionP = NULL;}
while (m_xcList.DeleteString(0) != LB_ERR);
m_xvEditCurDir = _T("");
UpdateData(FALSE);
}
|
CFtpConnectionクラスのオブジェクトはCInternetSessionクラスの内部で作成、破棄されるので、自分で破棄する必要はありません(というよりしてはいけません)。CInternetSessionクラスのオブジェクトは自分で破棄します。破棄すると自動的にFTPのコネクションが切断されます。
切断したら、リストボックスやカレントディレクトリの文字列を消去しておきます。
では、次はサーバからファイル一覧を取得して表示する部分を見ていきましょう。
// 表示更新
void CFtpClientDlg::Refresh(void)
{
int err = 0, lbErr = 0;
if (!err) if (!m_ftpConP) err = 1;
if (!err)
{
CFtpFileFind finder(m_ftpConP);
CString fileName;
BOOL bWorking = FALSE;
// カレントディレクトリ取得
m_ftpConP->GetCurrentDirectory(m_xvEditCurDir);
UpdateData(FALSE);
// ファイル一覧取得
while (m_xcList.DeleteString(0) != LB_ERR);
if ((bWorking = finder.FindFile()) == 0) err = 1;
if (!err)
{
while (bWorking)
{
bWorking = finder.FindNextFile();
fileName = finder.GetFileName();
if (finder.IsDirectory()) fileName = _T("[D]") +fileName;
lbErr = m_xcList.InsertString(-1, fileName);
if (lbErr == LB_ERR || lbErr == LB_ERRSPACE) err = 1;
if (err) break;
}
}
}
return;
}
|
まずはカレントディレクトリの表示を更新しておきます。カレントディレクトリはCFtpConnection::GetCurrentDirectory()で取得できます。引数にはCStringオブジェクトの参照を渡します。
次はカレントディレクトリにあるファイルの一覧を取得します。ファイル一覧の取得はCFtpFileFindクラスを使います。CFtpFileFindクラスのコンストラクタにCFtpConnectionオブジェクトへのポインタを渡します。
ファイル一覧取得の流れはプログラムを見るとわかると思いますが、CFtpFileFind::FindFile()関数で検索を開始します。その後はCFtpFileFind::FindNextFile()関数で一つずつファイルを検索していきます。ファイル名の取得はCFtpFileFind::GetFileName()関数でできます。
また、取得するものはファイルとディレクトリが混在しています。ディレクトリかどうかはCFileFind::IsDirectory()関数で判断できます。今回は簡易的に作っているので、ディレクトリだった場合は名前の頭に"[D]"をつけて区別しています。もちろんこれではファイル名の先頭に"[D]"がついているものがあった場合は区別できなくなるので、ちゃんと作る場合はディレクトリなのかどうかのフラグを別に持つように作らないといけません。
では各関数の詳細を解説していきます。
virtual BOOL CFtpFileFind::FindFile(
LPCTSTR pstrName = NULL,
DWORD dwFlags = INTERNET_FLAG_RELOAD
); |
| 説明: |
FTPファイル検索を開始する |
| 引数: |
pstrName:検索するファイルの名前。NULLの場合ワイルドカード(*)になる。
dwFlags:処理方法を指定するフラグ |
| 戻り値: |
正常終了した場合は0以外、それ以外の場合は0 |
現在選択されているブラシを取得するには、CDC::GetCurrentBrush()関数を使います。
| virtual BOOL CFtpFileFind::FindNextFile( ); |
| 説明: |
次のFTPファイルを検索する |
| 引数: |
なし |
| 戻り値: |
まだファイルがある場合は0以外、ディレクトリ内の最後のファイルを取得した場合やエラーが発生した場合は0 |
では、ここまでで一区切りにします。次回はディレクトリの移動や作成、削除を作っていきます。
|