このサイトでは、分析、カスタマイズされたコンテンツ、および広告に Cookie を使用します。このサイトを引き続き閲覧すると、Cookie の使用に同意するものと見なされます。
Hi, Developers,
straightapps.com ロゴ
作成 February 26, 2022
トップページ > Windows トップ > FTP でファイルをアップ&ダウンロード
line
Windows 開発
line

C++ で FTP 接続してサーバー上のファイルを操作するコードを紹介しています。

ウェブサイトを構築するには、 通常は管理ツールを使用したり、FTP ソフトを利用したりしますが、 データファイルなどの管理のため、自分でサーバーにアクセスしたいことがあるかもしれません。

Windows で C++ プログラムから FTP サーバーへのアクセスが非常に簡単でしたので、 何に使うかわかりませんが、ここにコードを残しています。

自分で FTP ソフトを作成したりするよりは、 無料でも優れた FTP ソフトがすぐに見つかりますので、 どんな用途で利用できるか、思いついたら追記します。

ここにあるコードの開発環境は Windows 10 Pro、Visual C++ 2015、 MFC ( Microsoft Foundation Class、マイクロソフト提供の高度な機能を持ったクラス群を使用するフレームワークです。 ) 利用です。

▼ セクション一覧

プロジェクトを作成する
指定フォルダのファイルを列挙する
ファイルをダウンロードする
ファイルをアップロードする

なお、本サイトのご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。

プロジェクトを作成する

投稿 February 26, 2022

Visual Studio を起動して、Visual C++ にある MFC アプリケーションを作成します。 ここでは単純にテスト目的ですのでダイアログベース・アプリにしていますが、おそらく何でも問題ありません。

忘れてはいけないのは、「高度な機能」のページで、 「Windows ソケット」にチェックを入れることです。

MFC アプリケーション ウィザード

新しいバージョンの Visual Studio では画面が異なるかもしれませんが、設定項目は同じだと思います。

ダイアログベースであれば、とりあえず IDOK ボタンのラベルを「接続」や「テスト」に書き換えて、 このボタン処理で FTP 接続機能を試します。

ちゃんとアプリにする場合は、UI や表示の工夫が必要ですが、ここでは扱いません。 例えばダイアログにドロップされたファイルをアップロードするような場合は、 「タイムスタンプを自由に変更する」の 「ダイアログでドロップファイルを受け入れる」セクション などを参考にしていただけます。

▲ページ先頭へ

指定フォルダのファイルを列挙する

投稿 February 26, 2022

ここでは Visual C++ で MFC ( Microsoft Foundation Class、マイクロソフト提供の高度な機能を持ったクラス群を使用するフレームワークです。 ) 利用を前提としていますので、事前にネットワーク処理に必要なヘッダーファイルをインクルードしておきます。

#include "afxinet.h"

IDOK ボタンのハンドラ OnBnClickedOk() に実装した順に記載します。

まず行うべきことは、WININET ライブラリを初期化するためにセッションオブジェクトを作成することです。 レジストリに記載のアクセスメソッドがデフォルトパラメータとして使用されるとされていますので、 つまり、コントロールパネルの "インターネット" アイコンからの設定値が使用されるようです。 詳しくは、 「CInternetSession クラス」 に記載されています。

CInternetSession sess(_T("My FTP Session"));

オブジェクト名は sess としていますが、もちろん何でも構いません。 引数としている「セッション名」も、何でも構いません。

続けて、FTP 接続を取得します。

CFtpConnection *pConnect = NULL;

try
{
	pConnect = sess.GetFtpConnection(_T("ftp.YourDomain.com"), _T("username"), _T("password"), 21, TRUE);

まず、途中でエラー(例外)が出たときのため、しばらくの処理を try でくくっています。

ftp ドメイン名やログインするためのユーザー名、パスワードなどは、 プロバイダやレンタルサーバーから提供されたもの、あるいは自前のものならその設定に従います。 21 はポート番号ですが、指定があればその値を使います。 事前に FTP ソフトで接続が確認できているのであれば、そこに記載した値を使えば間違いありません。

怖いので試しませんが、もしかすると(パスワード打ち間違いなどで)何度も接続に失敗すると、 アカウントがロックされたり、一定の時間、あるいは解除するまで接続できなくなったりするかもしれませんので、ご注意ください。

次のコードは確認用ですので、実際には不要です。

#if 1
	CString str;
	pConnect->GetCurrentDirectoryAsURL(str);
#endif

この場合、
ftp://ftp.YourDomain.com/
のような値が返されていました。

次のような呼び出しも試みました。

#if 1
	pConnect->GetCurrentDirectory(str);
#endif

この場合、返されたのは / のみでした。

	pConnect->SetCurrentDirectory(_T("WWW"));

#if 1
	pConnect->GetCurrentDirectory(str);
#endif

私がテストしたサーバーの場合、WWW サブフォルダにデータがありますので、 カレントディレクトリを WWW にするため、SetCurrentDirectory 関数を呼び出しました。 すると、GetCurrentDirectory 関数では、 /WWW が返るようになりました。

カレントディレクトリにあるファイルを列挙してみます。

	CFtpFileFind finder(pConnect);

	// ループを開始します。
	BOOL bWorking = finder.FindFile(_T("*"));

	while (bWorking)
	{
		bWorking = finder.FindNextFile();
		// finder.GetFileURL() では、"ftp://ftp.YourDomain.com/WWW" で終わってしまい、ファイル名が取れない
		// finder.GetFilePath() では、上記の場合、"/WWW" だけが返される
		// finder.GetFileName() で、ファイル名を取得できた

		if (finder.IsDirectory()) {
			str.Format(_T("[DIR] %s"), finder.GetFileName());
		}
		else {
			str.Format(_T("[FILE] %s"), finder.GetFileName());
		}
		// str を使って表示等を行います。
	}
}

try ブロックはここで終わります。

どこかでエラーとなった場合は、catch で取得します。

catch (CInternetException *pEx)
{
	TCHAR sz[1024];
	pEx->GetErrorMessage(sz, 1024);

	// sz を使って表示等を行います。

	pEx->Delete();
}

ひとまず、ファイルの列挙ができましたので、終了します。

if (pConnect != NULL){
	pConnect->Close();
	delete pConnect;
}
▲ページ先頭へ

ファイルをダウンロードする

投稿 February 26, 2022

あるとわかっているファイルをダウンロードしたい場合、 上記と同じ手順で CFtpConnection へのポインタ pConnect を取得した後、 下記のように実行します。

if (pConnect->GetFile(_T("data.dat"), _T("C:\\data\\data.dat"))) {
	// data.dat を取得できました。
}
else {
	// data.dat を取得できませんでした。
}

GetFile 関数の第 1 引数がネットワーク上のファイル名です。 サブフォルダにある場合は、事前に pConnect->SetCurrentDirectory 関数で移動しておきます。

第 2 引数はローカルのパスとファイル名です。 ファイル名を指定しているということは、ファイル名は変更可能である、ということになります。

呼び出し後は Close 関数を呼び忘れないようにします。

▲ページ先頭へ

ファイルをアップロードする

投稿 February 26, 2022

ローカルにあるファイルをアップロードしたい場合も、 まずは上記と同じ手順で CFtpConnection へのポインタ pConnect を取得します。 そのあと下記のように実行します。

if (pConnect->PutFile(_T("D:\\data\\data.png"), _T("data.png"), FTP_TRANSFER_TYPE_BINARY)) {
	// data.png をアップロードできました。
}
else {
	// data.png をアップロードできませんでした。
}

PutFile 関数の引数は GetFile 関数とは逆に、 第 1 引数がローカルのパスとファイル名です。

第 2 引数はネットワーク上のファイル名です。 サブフォルダにコピーしたい場合は、事前に pConnect->SetCurrentDirectory 関数で移動しておきます。

呼び出し後は Close 関数を呼び忘れないようにします。

▲ページ先頭へ
line
関連トピックス
line

Windows 開発トップ
Windows 開発関連の情報を、書いています。

line
その他のおすすめ
line

おすすめ記事はありません。



© 2017-2022 StraightApps.com 無断転載を禁じます。No reproduction without permission.