
1. wxWidgets 설치는 아래를 참고하세요
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 파일을 만들면 테스트 가능합니다.
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
'C++ GUI' 카테고리의 다른 글
| C++ GUI : wxWidgets & POCO 라이브러리를 REST API Client 만들기 (0) | 2026.06.01 |
|---|---|
| C++ GUI : wxWidgets의 wxSimplebook/wxNotebook사용하기 (0) | 2026.06.01 |
| C++ GUI : wxWidgets에서 Login 구현하기 (0) | 2026.05.17 |
| C++ GUI : Console에서 mariaDB ADO 사용하기 (0) | 2026.05.10 |
| C++ GUI : Console에서 mariaDB C/C++ Connector 사용하기 (0) | 2026.05.10 |