• Qt之FTP实现-QFtp实例操作


    前言

    前面写了三篇关于FTP的blog,关于QFtp相关介绍,FTP本地环境搭建。
    地址如下:
    Qt三种方式实现FTP上传功能
    Qt之FTP实现–QFtp篇
    win11系统搭建FTP服务器超详细流程

    今天具体来根据QFtp写个实例介绍如何在实际项目中使用其相关接口。
    主要为了演示接口使用,所以做了个简单的UI,没那么精致,凑合着看。

    在这里插入图片描述


    本文Demo下载


    正文

    以上示例包含了FTP登录,为方便演示,本次连接的FTP服务器就是上篇文章中介绍的在windows本机搭建的FTP服务器。Demo功能包括:选择文件夹进行批量上传文件,列举FTP服务器上的所有文件,以及文件实时上传进度 这几个重要功能。其实QFTP还提供了很多其他接口,用法都是差不多的,可以举一反三。
    具体接口如下,前面的文章也有介绍过:

        int setProxy(const QString &host, quint16 port);
        int connectToHost(const QString &host, quint16 port=21);
        int login(const QString &user = QString(), const QString &password = QString());
        int close();
        int setTransferMode(TransferMode mode);
        int list(const QString &dir = QString());
        int cd(const QString &dir);
        int get(const QString &file, QIODevice *dev=0, TransferType type = Binary);
        int put(const QByteArray &data, const QString &file, TransferType type = Binary);
        int put(QIODevice *dev, const QString &file, TransferType type = Binary);
        int remove(const QString &file);
        int mkdir(const QString &dir);
        int rmdir(const QString &dir);
        int rename(const QString &oldname, const QString &newname);
    
        int rawCommand(const QString &command);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    包含的信号:

    Q_SIGNALS:
        void stateChanged(int);
        void listInfo(const QUrlInfo&);
        void readyRead();
        void dataTransferProgress(qint64, qint64);
        void rawCommandReply(int, const QString&);
    
        void commandStarted(int);
        void commandFinished(int, bool);
        void done(bool);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其他详细接口可以查看qftp.h 源码。

    相关接口的介绍及使用在 Qt之FTP实现–QFtp篇 中已经详细说明。

    需要注意的是,做这种批量上传,由于上传过程是异步的,我们要让文件一个个的依次上传,就得等前一个文件执行完后再执行下一个文件,所以需要做成同步执行,所以这里就要用到QEventLoop来实现。
    然后考虑到文件大小以及内存占用问题,不能直接将文件readAll() 后进行传输。

    上传部分代码:

    void Widget::on_uploadBtn_clicked()
    {
        auto path = ui->folderEdit->text();
        QDir dir(path);
        if(dir.exists()){
            ui->progressBar->setVisible(true);
            auto fileLst = dir.entryInfoList(QDir::Files);
            for(const auto& it : fileLst){
    
                QFile *file = new QFile(it.filePath(),this);
                if(!file->open(QIODevice::ReadOnly)){
                    qDebug() << __FUNCTION__ <<"file open failed.";
                    if(m_loop.isRunning())
                        m_loop.exit();
                    continue;
                }
                ui->tips->setText(QString::fromLocal8Bit("当前正在上传:") + it.fileName());
                m_ftp.put(file,it.fileName());
                m_loop.exec();
            }
            ui->tips->setText(QString::fromLocal8Bit("已完成所有文件上传"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    另外,所有的操作都会有以下两个信号发出

    void commandStarted(int);
    void commandFinished(int, bool);
    
    • 1
    • 2

    所以我们可以通过连接此信号,然后判断当前command,来区分当前操作内容,从而执行相关内容,比如执行 “获取文件列表”,**“删除文件”**等操作,可以在commandFinished信号后执行下一步操作。

    操作命令包括:

    enum Command {
            None,
            SetTransferMode,
            SetProxy,
            ConnectToHost,
            Login,
            Close,
            List,
            Cd,
            Get,
            Put,
            Remove,
            Mkdir,
            Rmdir,
            Rename,
            RawCommand
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    比如获取文件列表,commandFinished后就可以去更新UI:

    	connect(&m_ftp, &QFtp::listInfo, this, [&](QUrlInfo info){
            m_fileList.append(info.name());
        });
    
        connect(&m_ftp,&QFtp::commandFinished,this,[&](){
            if(m_ftp.currentCommand() == QFtp::List){
                qDebug() << "commandFinished. QFtp::List " << m_fileList ;
                ui->listWidget->addItems(m_fileList);
                if(m_loop.isRunning())
                    m_loop.exit();
            }
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    其他功能可以以此类推。

    最后 附上演示Demo下载。

    若有其他使用上的疑问可以私信或评论进行咨询。


    本文Demo下载


  • 相关阅读:
    【PMP/软考】软件需求的三个主要层次:业务需求、用户需求和功能需求解释及实例解析
    电信保温杯笔记——《统计学习方法(第二版)——李航》第17章 潜在语义分析
    vue监听Enter键
    数据治理资料整理合集
    【跨境电商】全渠道客户服务终极指南(一):概念,重要性与优势
    初阶数据结构学习记录——열 二叉树(3)链式
    记一次使用动态引入vue组件的经历
    振弦采集模块数字接口
    docker 安装cloudreve
    新建SpringCloud电商后台项目
  • 原文地址:https://blog.csdn.net/luoyayun361/article/details/125418046