본문 바로가기
C++ GUI

C++ GUI : wxWidgets에서 wxFTP 사용하기

by taekho 2026. 5. 18.

 

1. wxWidgets 설치는 아래를 참고하세요

https://taekho.tistory.com/5

 

C++ GUI : wxWidgets 설치

Visual Studio 2022( Community 판) 기준으로 설치를 진행함.참고 : Visual Studio Community 다운로드 - https://visualstudio.microsoft.com/ko/vs/community/ Visual Studio Community | 최신 무료 버전 다운로드Windows, Android 및 iOS용

taekho.tistory.com

 

2. App.h 파일을 추가합니다.

#pragma once
#include <wx/wx.h>

class MyApp : public wxApp {
public:
	virtual bool OnInit();
};

 

3. App.cpp 파일을 추가합니다.

#include "App.h"
#include <wx/socket.h>
#include "MainFrame.h"

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit() {
	wxSocketBase::Initialize();

	MyFrame* frame = new MyFrame("wxFTP Test", wxDefaultPosition, wxSize(600, 600));	

	frame->Show(true);
	return true;
}

 

4. MainFrame.h 파일을 추가합니다.

#pragma once
#include <wx/wx.h>

class MyFrame : public wxFrame {
public:
	MyFrame(const wxString& title, const wxPoint& pos, const wxSize size);

private:	
	void OnDownloadData(wxCommandEvent& event);
	void OnDownloadFile(wxCommandEvent& event);	
	void OnUploadFile(wxCommandEvent& event);

	wxTextCtrl* text;
	wxTextCtrl* textFileName;

};

 

5. MainFrame.cpp 파일을 추가합니다.

#include "MainFrame.h"
#include <wx/protocol/ftp.h>
#include <thread>
#include <wx/wfstream.h>
#include <wx/filename.h>

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize size)
	: wxFrame(nullptr, wxID_ANY, title, pos, size)
{
	this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENU));
	CreateStatusBar();
	SetStatusText("Welcome to wxWidgets!");

	auto sizer = new wxBoxSizer(wxHORIZONTAL);

	wxStaticText* staticTextFileName = new wxStaticText(this, wxID_ANY, "File name:", wxPoint(10, 10));
	sizer->Add(staticTextFileName, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);

	textFileName = new wxTextCtrl(this, wxID_ANY, "", wxPoint(70, 10), wxSize(100, 25));// , wxTE_MULTILINE | wxTE_READONLY);
	sizer->Add(textFileName, 0, wxALL, 5);

	wxButton* downloadButton = new wxButton(this, wxID_ANY, "Download Data", wxPoint(10, 40));
	sizer->Add(downloadButton, 0, wxALL, 5);

	wxButton* downloadfileButton = new wxButton(this, wxID_ANY, "Download File", wxPoint(120, 40));
	sizer->Add(downloadfileButton, 0, wxALL, 5);	

	wxButton* uploadButton = new wxButton(this, wxID_ANY, "Upload File", wxPoint(230, 40));
	sizer->Add(uploadButton, 0, wxALL, 5);

	text = new wxTextCtrl(this, wxID_ANY, "", wxPoint(10, 70), wxSize(550, 400), wxTE_MULTILINE | wxTE_READONLY);
	sizer->Add(text, 1, wxEXPAND);

	downloadButton->Bind(wxEVT_BUTTON, &MyFrame::OnDownloadData, this);
	downloadfileButton->Bind(wxEVT_BUTTON, &MyFrame::OnDownloadFile, this);
	uploadButton->Bind(wxEVT_BUTTON, &MyFrame::OnUploadFile, this);
}

void MyFrame::OnUploadFile(wxCommandEvent& event) {
	wxString source = wxFileSelector(wxT("Select a file to upload"), wxEmptyString, wxEmptyString, wxEmptyString, wxT("*.*"), wxFD_OPEN);
	if (source.IsEmpty())  return;
	auto f = [this, source]() {
		auto appendText = [this](const wxString& message) {
			CallAfter([this, message]() {
				text->AppendText(message);
				});
			};

		wxFTP ftp;
		ftp.SetUser("test");
		ftp.SetPassword("test");
		ftp.Connect("127.0.0.1", 21);
		if (ftp.IsConnected()) {
			appendText("Connected to FTP server\n");
			char ret = ftp.SendCommand("OPTS UTF8 ON");
			appendText(wxString::Format("Sent command: OPTS UTF8 ON, return code: %c\n", ret)); // 2 OK
			ftp.SetBinary();

			wxFileName localFile(source);
			wxString requestedName = localFile.GetFullName(); 
            
			auto os{ ftp.GetOutputStream(requestedName) };
			auto in{ new wxFileInputStream(source) };
			if (os && os->IsOk() && in && in->IsOk()) {
				appendText("Uploading file: " + source + " as " + requestedName + "\n");
				std::vector<char> data(65536);
				while (in->CanRead()) {
					in->Read(data.data(), data.size());
					if (in->LastRead() > 0) {
						os->Write(data.data(), in->LastRead());
					}
				}
				appendText("Finished uploading file: " + source + "\n\n ---------------------------------------------\n\n");
			}
			else {
				appendText("Failed to upload file: " + source + "\nFTP reply: " + ftp.GetLastResult() + "\n");
				CallAfter([source]() {
					wxMessageBox("Could not upload file: " + source, "Error", wxICON_ERROR);
					});
			}
		}
		else {
			CallAfter([]() {
				wxMessageBox("Could not connect to FTP server", "Error", wxICON_ERROR);
				});
		}
		ftp.Close();
		};
	std::thread t{ f };
	t.detach();
}

void MyFrame::OnDownloadFile(wxCommandEvent& event) {
	wxString dest = wxDirSelector(wxT("Where to save the downloaded file?"), wxEmptyString, wxFD_SAVE);
	if (dest.IsEmpty())  return;

	auto f = [this, dest]() {
		auto appendText = [this](const wxString& message) {
			CallAfter([this, message]() {
				text->AppendText(message);
				});
			};

		wxFTP ftp;

		ftp.SetUser("anonymous");
		ftp.SetPassword("anonymous");
		ftp.Connect("127.0.0.1", 21);
		if (ftp.IsConnected()) {
			appendText("Connected to FTP server\n");

			char ret = ftp.SendCommand("OPTS UTF8 ON");
			appendText(wxString::Format("Sent command: OPTS UTF8 ON, return code: %c\n", ret)); // 2 OK

			ftp.SetBinary();

			wxString filename = textFileName->GetValue();
			filename.Trim(true).Trim(false);

			wxString requestedName = filename;
			auto in{ ftp.GetInputStream(requestedName) };
			auto os{ new wxFileOutputStream(dest + wxT("/") + wxFileNameFromPath(requestedName)) };

			if (in && in->IsOk()) {
				appendText("Reading file: " + requestedName + "\n");
				std::vector<char> data(65536);
				wxMemoryBuffer fileData;
				do
				{
					in->Read(data.data(), data.size());
					if (in->LastRead() > 0) {
						os->Write(data.data(), in->LastRead());
					}
				} while (in->LastRead() > 0);

				wxString content = wxString::FromUTF8(static_cast<const char*>(fileData.GetData()), fileData.GetDataLen());
				appendText("Finished downloading file: " + requestedName + "\n\n ---------------------------------------------\n\n");
			}
			else {
				appendText("Failed to read file: " + requestedName + "\nFTP reply: " + ftp.GetLastResult() + "\n");
				CallAfter([requestedName]() {
					wxMessageBox("Could not read file: " + requestedName, "Error", wxICON_ERROR);
					});
			}
		}
		else {
			CallAfter([]() {
				wxMessageBox("Could not connect to FTP server", "Error", wxICON_ERROR);
				});
		}
		
		ftp.Close();
		};

	std::thread t{ f };
	t.detach();
}


void MyFrame::OnDownloadData(wxCommandEvent& event) {
	auto f = [this]() {
		auto appendText = [this](const wxString& message) {
			CallAfter([this, message]() {
				text->AppendText(message);
			});
		};

		wxFTP ftp;

		ftp.SetUser("anonymous");
		ftp.SetPassword("anonymous");
		ftp.Connect("127.0.0.1", 21);
		if (ftp.IsConnected()) {
			appendText("Connected to FTP server\n");

			char ret = ftp.SendCommand("OPTS UTF8 ON");
			appendText(wxString::Format("Sent command: OPTS UTF8 ON, return code: %c\n", ret)); // 2 OK

			ftp.SetBinary();
			
			wxString filename = textFileName->GetValue();
			filename.Trim(true).Trim(false);

			wxString requestedName = filename;
			auto in{ftp.GetInputStream(requestedName)};

			if (in && in->IsOk()) {
				appendText("Reading file: " + requestedName + "\n");
				std::vector<char> data(65536);
				wxMemoryBuffer fileData;
				do
				{
					in->Read(data.data(), data.size());
					if (in->LastRead() > 0) {
						fileData.AppendData(data.data(), in->LastRead());
					}
				} while (in->LastRead() > 0);

				wxString content = wxString::FromUTF8(static_cast<const char*>(fileData.GetData()), fileData.GetDataLen());
				appendText(content + "\n\n ---------------------------------------------\n\n");
			}
			else {
				appendText("Failed to read file: " + requestedName + "\nFTP reply: " + ftp.GetLastResult() + "\n");
				CallAfter([requestedName]() {
					wxMessageBox("Could not read file: " + requestedName, "Error", wxICON_ERROR);
					});
			}			
		}
		else {
			CallAfter([]() {
				wxMessageBox("Could not connect to FTP server", "Error", wxICON_ERROR);
				});
		}

		ftp.Close();
		};

	std::thread t{ f };
	t.detach();
}

 

6. FTP Server를 실행합니다.

    - 간단한 테스트를 위해 아래 Python FTP Server 를 참고하세요

    - C 드라이버에 ftp_test_dir/FTP폴더를 만든 후 test.txt 파일을 만들면 테스트 가능합니다.

https://taekho.tistory.com/13

 

Python : Python FTP Server(pyftpdlib라이브러리)사용법

1. 설치pip install pyftpdlib 2. 서버 파일(ftp_server.py) 작성 from pyftpdlib.authorizers import DummyAuthorizerfrom pyftpdlib.handlers import FTPHandlerfrom pyftpdlib.servers import FTPServerFTP_DIRECTORY = "c:/ftp_test_dir/FTP/" # Published folder

taekho.tistory.com