.pro文件
#-------------------------------------------------
#
# Project created by QtCreator 2024-07-16T13:19:03
#
#-------------------------------------------------
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = untitled
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
FTPManager.cpp
HEADERS += \
FTPManager.h
FORMS += \
FTPManager.ui
LIBS += -lWininet
.h文件
#ifndef FTPMANAGER_H
#define FTPMANAGER_H
#include <Windows.h>
#include <Wininet.h>
#include <QtDebug>
#include <QListWidget>
#include <QString>
#include <QFileDialog>
#include <QObject>
class FTPManager : public QObject
{
Q_OBJECT
public:
FTPManager(); // 构造函数,初始化 WinINet
~FTPManager(); // 析构函数,关闭连接
// 连接到 FTP 服务器
bool connectToFTP(const wchar_t* szHostName, const wchar_t* szUserName, const wchar_t* szPassword);
// 断开 FTP 连接
void disconnectFromFTP();
// 列出 FTP 服务器上指定路径下的所有文件和文件夹
bool listFilesAndDirectories(const wchar_t* szUrlPath, QListWidget* listWidget);
// 下载 FTP 服务器上的单个文件
bool downloadFileFromFTP(const wchar_t* szFileName, const wchar_t* szLocalPath);
// 下载 FTP 服务器上指定路径的所有文件
bool downloadDirectoryFromFTP(const wchar_t* szUrlPath, const wchar_t* szLocalPath);
private:
HINTERNET m_hInternet; // WinINet 打开的 Internet 连接句柄
HINTERNET m_hConnect; // FTP 连接句柄
};
#endif // FTPMANAGER_H
.cpp文件
#include "FTPManager.h"
FTPManager::FTPManager()
: m_hInternet(NULL), m_hConnect(NULL)
{
// 初始化 WinINet
m_hInternet = InternetOpen(L"WinInet Ftp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!m_hInternet)
{
qDebug() << "InternetOpen failed: " << GetLastError();
}
}
FTPManager::~FTPManager()
{
// 析构函数,关闭 WinINet 相关资源
if (m_hConnect)
InternetCloseHandle(m_hConnect);
if (m_hInternet)
InternetCloseHandle(m_hInternet);
}
bool FTPManager::connectToFTP(const wchar_t* szHostName, const wchar_t* szUserName, const wchar_t* szPassword)
{
if (!m_hInternet)
{
qDebug() << "Not connected to Internet";
return false;
}
// 连接到 FTP 服务器
m_hConnect = InternetConnect(m_hInternet, szHostName, INTERNET_DEFAULT_FTP_PORT, szUserName, szPassword, INTERNET_SERVICE_FTP, 0, 0);
if (!m_hConnect)
{
qDebug() << "InternetConnect failed: " << GetLastError();
return false;
}
return true;
}
void FTPManager::disconnectFromFTP()
{
// 断开 FTP 连接
if (m_hConnect)
{
InternetCloseHandle(m_hConnect);
m_hConnect = NULL;
}
}
bool FTPManager::listFilesAndDirectories(const wchar_t* szUrlPath, QListWidget* listWidget)
{
if (!m_hConnect)
{
qDebug() << "Not connected to FTP server";
return false;
}
std::wstring searchPath = szUrlPath;
if (searchPath.back() != L'/')
searchPath += L"/";
WIN32_FIND_DATAW findData;
RtlZeroMemory(&findData, sizeof(WIN32_FIND_DATAW));
// 执行 FTP 的查找操作
HINTERNET hFind = FtpFindFirstFile(m_hConnect, (searchPath + L"*").c_str(), &findData, INTERNET_FLAG_RELOAD, 0);
if (hFind == NULL)
{
qDebug() << "FtpFindFirstFile failed: " << GetLastError();
return false;
}
BOOL bNext = TRUE;
// 循环读取文件和文件夹信息,并添加到 QListWidget 中显示
while (bNext)
{
// 如果是文件夹,则输出文件夹名称
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
std::wstring fileName = findData.cFileName;
QString qFileName = QString::fromStdWString(fileName);
QListWidgetItem* item = new QListWidgetItem(qFileName);
listWidget->addItem(item);
}
bNext = InternetFindNextFile(hFind, &findData);
}
InternetCloseHandle(hFind);
return true;
}
bool FTPManager::downloadFileFromFTP(const wchar_t* szFileName, const wchar_t* szLocalPath)
{
if (!m_hConnect)
{
qDebug() << "Not connected to FTP server";
return false;
}
// 打开 FTP 服务器上的文件
HINTERNET hFile = FtpOpenFile(m_hConnect, szFileName, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY, 0);
if (!hFile)
{
qDebug() << "FtpOpenFile failed: " << GetLastError();
return false;
}
std::wstring localFilePath = szLocalPath;
localFilePath += L"\\";
localFilePath += szFileName;
// 在本地创建文件
HANDLE hLocalFile = CreateFile(localFilePath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hLocalFile == INVALID_HANDLE_VALUE)
{
qDebug() << "CreateFile failed: " << GetLastError();
InternetCloseHandle(hFile);
return false;
}
DWORD bytesRead = 0;
BYTE buffer[1024];
BOOL bRet = true;
// 从 FTP 服务器读取文件内容,并写入到本地文件中
while (InternetReadFile(hFile, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0)
{
DWORD bytesWritten = 0;
if (!WriteFile(hLocalFile, buffer, bytesRead, &bytesWritten, NULL))
{
qDebug() << "WriteFile failed: " << GetLastError();
bRet = false;
break;
}
}
CloseHandle(hLocalFile);
InternetCloseHandle(hFile);
if (bRet)
{
qDebug() << "File downloaded successfully: " << QString::fromStdWString(localFilePath);
}
return bRet;
}
bool FTPManager::downloadDirectoryFromFTP(const wchar_t* szUrlPath, const wchar_t* szLocalPath)
{
if (!m_hConnect)
{
qDebug() << "Not connected to FTP server";
return false;
}
std::wstring searchPath = szUrlPath;
if (searchPath.back() != L'/')
searchPath += L"/";
WIN32_FIND_DATAW findData;
RtlZeroMemory(&findData, sizeof(WIN32_FIND_DATAW));
// 查找 FTP 服务器上的文件和文件夹
HINTERNET hFind = FtpFindFirstFile(m_hConnect, (searchPath + L"*").c_str(), &findData, INTERNET_FLAG_RELOAD, 0);
if (hFind == NULL)
{
qDebug() << "FtpFindFirstFile failed: " << GetLastError();
return false;
}
BOOL bNext = TRUE;
BOOL bRet = true;
// 下载 FTP 服务器上指定路径的所有文件到本地目录
while (bNext)
{
// 如果是文件,则下载文件
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
bRet = downloadFileFromFTP(findData.cFileName, szLocalPath);
if (!bRet)
break;
}
bNext = InternetFindNextFile(hFind, &findData);
}
InternetCloseHandle(hFind);
return bRet;
}
main.cpp
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QListWidget>
#include <QPushButton>
#include <QFileDialog>
#include "FTPManager.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget window;
QVBoxLayout layout(&window);
QListWidget listWidget;
QPushButton btnList("列出文件");
QPushButton btnDownloadFile("下载文件");
QPushButton btnDownloadAll("下载全部");
const wchar_t* szHostName = L"192.168.0.103"; // FTP服务器地址
const wchar_t* szUserName = L"root"; // FTP登录用户名
const wchar_t* szPassword = L"root"; // FTP登录密码
const wchar_t* szUrlPath = L"/"; // FTP服务器上要列出文件和文件夹的路径
const wchar_t* szLocalPath = L"C:\\Users\\ROG10030\\Desktop\\FTPDownload"; // 本地保存路径
FTPManager ftpManager;
// 点击按钮,列出文件和文件夹列表
QObject::connect(&btnList, &QPushButton::clicked, [&]() {
listWidget.clear();
if (ftpManager.connectToFTP(szHostName, szUserName, szPassword))
{
qDebug() << "已连接到 FTP 服务器";
ftpManager.listFilesAndDirectories(szUrlPath, &listWidget);
ftpManager.disconnectFromFTP();
}
});
// 点击按钮,下载单个文件
QObject::connect(&btnDownloadFile, &QPushButton::clicked, [&]() {
QString fileName = QFileDialog::getSaveFileName(nullptr, "保存文件", QDir::homePath());
if (!fileName.isEmpty())
{
std::wstring wsFileName = fileName.toStdWString();
if (ftpManager.connectToFTP(szHostName, szUserName, szPassword))
{
qDebug() << "已连接到 FTP 服务器";
ftpManager.downloadFileFromFTP(wsFileName.c_str(), szLocalPath);
ftpManager.disconnectFromFTP();
}
}
});
// 点击按钮,下载整个目录
QObject::connect(&btnDownloadAll, &QPushButton::clicked, [&]() {
if (ftpManager.connectToFTP(szHostName, szUserName, szPassword))
{
qDebug() << "已连接到 FTP 服务器";
CreateDirectory(szLocalPath, NULL);
ftpManager.downloadDirectoryFromFTP(szUrlPath, szLocalPath);
ftpManager.disconnectFromFTP();
}
});
layout.addWidget(&btnList);
layout.addWidget(&listWidget);
layout.addWidget(&btnDownloadFile);
layout.addWidget(&btnDownloadAll);
window.setLayout(&layout);
window.resize(400, 300);
window.show();
return a.exec();
}
点击列出文件则会将此目录下的文件显示到list中,下载全部没问题,单个下载需要选择文件,进行处理(未完全实现)