C++链接FTP服务器并下载数据(在qt中编写)

.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中,下载全部没问题,单个下载需要选择文件,进行处理(未完全实现)

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值