QT实现Ftp客户端的三种方法及工程实例

news2024/12/23 12:17:18

1.Qt项目中实现的FTP传输功能的三种方式

(1)QFtp

     QFtp 是 Qt4 中专门负责 FTP 传输的类,包括创建目录、删除目录、删除文件、获取文件列表、上传、下载等等常规操作。

     注意:QT5中已经移除,如果需要用需要自己添加QFtp类文件。

(2)QNetworkAccessManager

     是 Qt 专门负责网络请求的模块,包含了 http 的 post、get、put,put 用来 Qt5 实现 FTP 上传功能,get 用来实现下载功能,仅仅只能上传下载,功能较少。

(3)POCO FTPClientSession

     FTPClientSession 是 POCO 中网络模块里负责实现 FTP 的类,接口如下,POCO 是目前最流行的 C++ 轻量级封装库之一,里面包含了很多常用的封装库,不是只有FTP功能。

     注意:其属于第三方库

2.三种方式的区别

(1)QFtp:

简单易用:QFtp 是Qt提供的一个简单的FTP客户端类,它提供了FTP操作的基本功能,并且使用相对简单。

同步操作:QFtp 主要基于同步操作,这意味着代码更直观,容易理解。

缺点:

不支持FTP over SSL/TLS:QFtp 不支持通过SSL/TLS加密的FTP连接,这在需要安全传输时是一个限制。

不支持异步操作:对于大型文件传输或需要同时处理多个FTP请求的应用,同步操作可能会导致界面冻结或性能问题。

在Qt5中,QFtp 已被标记为弃用,如果用要单独加入QFtp类

(2)QNetworkAccessManager

优点:简单,集成度高;

异步操作:QNetworkAccessManager 支持异步操作,这使得它更适合处理大型文件传输或多个并发请求。

支持HTTPS:与QFtp 不同,QNetworkAccessManager 支持通过HTTPS进行安全传输。

灵活性强:你可以使用它来发送和接收HTTP请求,不仅限于FTP。

缺点:

使用QNetworkAccessManager 实现FTP功能需要更多的代码和设置,相比QFtp 来说更复杂。

QNetworkAccessManager虽然也支持 FTP 通信,但其主要侧重于 HTTP 请求处理,FTP 功能相对较弱。

(3)FTPClientSession

优点:

专业的FTP实现:FTPClientSession(需要引入第三方库),提供了比QFtp 和 QNetworkAccessManager 更全面和专业的FTP功能。

支持FTP over SSL/TLS:通常,专业的FTP客户端库会支持FTP over SSL/TLS,这对于安全传输是必要的。

异步和同步操作:专业的FTP客户端库通常支持异步和同步操作,这使得它们更灵活。

缺点:

需要第三方库:FTPClientSession 可能不是Qt标准库的一部分,这意味着你需要集成第三方库,这可能会增加项目的复杂性。

学习曲线:如果你之前没有使用过类似的库,可能需要一些时间来学习和理解它的API和工作方式。

(4)总结

对于简单的FTP任务,并且不需要加密或异步操作,QFtp 可能是一个不错的选择。

对于需要异步操作和/或HTTPS支持的项目,QNetworkAccessManager 是一个合理的选择。尽管它的FTP功能有限,但它通常能满足大多数基本需求。

对于需要全面和专业的FTP功能,特别是需要FTP over SSL/TLS支持的项目,使用像FTPClientSession 这样的专业FTP客户端库可能是最佳选择。

3.代码示例  

(1).采用QFtp库,qt5.12开发

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include "qftp.h"

#include <QTextCodec>

#include <QFile>

#include <QTreeWidgetItem>

MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent),

    ui(new Ui::MainWindow)

{

    ui->setupUi(this);

    ui->progressBar->setValue(0);

    connect(ui->fileList, &QTreeWidget::itemActivated,

            this, &MainWindow::processItem);

}

MainWindow::~MainWindow()

{

    delete ui;

}

void MainWindow::ftpCommandStarted(int)

{

    int id = ftp->currentCommand();

    switch (id)

    {

    case QFtp::ConnectToHost :

        ui->label->setText(tr("正在连接到服务器…"));

        break;

    case QFtp::Login :

        ui->label->setText(tr("正在登录…"));

        break;

    case QFtp::Get :

        ui->label->setText(tr("正在下载…"));

        break;

    case QFtp::Close :

        ui->label->setText(tr("正在关闭连接…"));

    }

}

void MainWindow::ftpCommandFinished(int, bool error)

{

    if(ftp->currentCommand() == QFtp::ConnectToHost) {

        if (error)

            ui->label->setText(tr("连接服务器出现错误:%1").arg(ftp->errorString()));

        else ui->label->setText(tr("连接到服务器成功"));

    } else if (ftp->currentCommand() == QFtp::Login) {

        if (error)

            ui->label->setText(tr("登录出现错误:%1").arg(ftp->errorString()));

        else {

            ui->label->setText(tr("登录成功"));

            ftp->list();

        }

    } else if (ftp->currentCommand() == QFtp::Get) {

        if(error)

            ui->label->setText(tr("下载出现错误:%1").arg(ftp->errorString()));

        else {

            ui->label->setText(tr("已经完成下载"));

            file->close();

        }

        ui->downloadButton->setEnabled(true);

    } else if (ftp->currentCommand() == QFtp::List) {

        if (isDirectory.isEmpty())

        {

            ui->fileList->addTopLevelItem(

                        new QTreeWidgetItem(QStringList()<< tr("<empty>")));

            ui->fileList->setEnabled(false);

            ui->label->setText(tr("该目录为空"));

        }

    } else if (ftp->currentCommand() == QFtp::Close) {

        ui->label->setText(tr("已经关闭连接"));

    }

}

// 连接按钮

void MainWindow::on_connectButton_clicked()

{

    ui->fileList->clear();

    currentPath.clear();

    isDirectory.clear();

    ui->progressBar->setValue(0);

    ftp = new QFtp(this);

    connect(ftp, &QFtp::commandStarted, this,

            &MainWindow::ftpCommandStarted);

    connect(ftp, &QFtp::commandFinished,

            this, &MainWindow::ftpCommandFinished);

    connect(ftp, &QFtp::listInfo, this, &MainWindow::addToList);

    connect(ftp, &QFtp::dataTransferProgress,

            this, &MainWindow::updateDataTransferProgress);

    QString ftpServer = ui->ftpServerLineEdit->text();

    QString userName = ui->userNameLineEdit->text();

    QString passWord = ui->passWordLineEdit->text();

    ftp->connectToHost(ftpServer, 21);

    ftp->login(userName, passWord);

}

void MainWindow::addToList(const QUrlInfo &urlInfo)

{

    // 注意:因为服务器上文件使用UTF-8编码,所以要进行编码转换,这样显示中文才不会乱码

    QString name = QString::fromUtf8(urlInfo.name().toLatin1());

    QString owner = QString::fromUtf8(urlInfo.owner().toLatin1());

    QString group = QString::fromUtf8(urlInfo.group().toLatin1());

    QTreeWidgetItem *item = new QTreeWidgetItem;

    item->setText(0, name);

    item->setText(1, QString::number(urlInfo.size()));

    item->setText(2, owner);

    item->setText(3, group);

    item->setText(4, urlInfo.lastModified().toString("yyyy-MM-dd"));

    QPixmap pixmap(urlInfo.isDir() ? "../myFTP/dir.png" : "../myFTP/file.png");

    item->setIcon(0, pixmap);

    isDirectory[name] = urlInfo.isDir();

    ui->fileList->addTopLevelItem(item);

    if (!ui->fileList->currentItem()) {

        ui->fileList->setCurrentItem(ui->fileList->topLevelItem(0));

        ui->fileList->setEnabled(true);

    }

}

void MainWindow::processItem(QTreeWidgetItem *item, int)

{

    // 如果这个文件是个目录,则打开

    if (isDirectory.value(item->text(0))) {

        // 注意:因为目录名称可能是中文,在使用ftp命令cd()前需要先进行编码转换

        QString name = QLatin1String(item->text(0).toUtf8());

        ui->fileList->clear();

        isDirectory.clear();

        currentPath += "/";

        currentPath += name;

        ftp->cd(name);

        ftp->list();

        ui->cdToParentButton->setEnabled(true);

    }

}

// 返回上级目录按钮

void MainWindow::on_cdToParentButton_clicked()

{

    ui->fileList->clear();

    isDirectory.clear();

    currentPath = currentPath.left(currentPath.lastIndexOf('/'));

    if (currentPath.isEmpty()) {

        ui->cdToParentButton->setEnabled(false);

        ftp->cd("/");

    } else {

        ftp->cd(currentPath);

    }

    ftp->list();

}

// 下载按钮

void MainWindow::on_downloadButton_clicked()

{

    // 注意:因为文件名称可能是中文,所以在使用get()函数前需要进行编码转换

    QString fileName = ui->fileList->currentItem()->text(0);

    QString name = QLatin1String(fileName.toUtf8());

    file = new QFile(fileName);

    if (!file->open(QIODevice::WriteOnly)) {

        delete file;

        return;

    }

    ui->downloadButton->setEnabled(false);

    ftp->get(name, file);

}

void MainWindow::updateDataTransferProgress(qint64 readBytes,qint64 totalBytes)

{

    ui->progressBar->setMaximum(totalBytes);

    ui->progressBar->setValue(readBytes);

}

(2)测试界面

(3)完整工程代码下载:https://download.csdn.net/download/xieliru/88906720

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1489526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

day6 数组 嵌套循环

1&#xff1a;打印杨辉三角 91 int arr[6][6];92 int i,j0;93 for(i0;i<6;i)94 {95 for(j0;j<i;j) 96 {97 if(j0||ij)98 {99 arr[i][j]1; …

2.3 shl,shr,inc,dec,xchg,neg指令,中断int指令

汇编语言 1. shl左移指令 shl是逻辑左移指令&#xff0c;它的功能是将一个reg或内存单元中的数据向左移位&#xff1b;将最后移出的一位写入cf中&#xff1b;最低位用0补充shl&#xff1a;shift left例如&#xff1a;0100 1000b 往左移一位&#xff0c;变成10010000b&#xf…

Vue.js中的diff算法:让虚拟DOM更高效

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

C++ Primer Plus Sixth Edition - 下载电子书与源代码

C Primer Plus Sixth Edition - 下载电子书与源代码 1. C Primer Plus, 6th Edition1.1. Download the source code files1.2. 下载源代码文件 2. C Primer Plus, Sixth Edition (PDF)3. Table of ContentsReferences 1. C Primer Plus, 6th Edition C Primer Plus, 6th Editi…

xss.haozi.me:0x02

"><script>alert(1)</script> 这样就成功了

07. Nginx进阶-Nginx负载均衡

简介 负载均衡 什么是负载均衡&#xff1f; 负载均衡&#xff0c;英文名称为Load Balance&#xff0c;其含义就是指将负载&#xff08;工作任务&#xff09;进行平衡、分摊到多个操作单元上进行运行。 Nginx负载均衡 什么是Nginx负载均衡&#xff1f; Nginx负载均衡可以大…

redis07 持久化(RDB、AOF)

思维草图 redis持久化认识 Redis是一个基于内存的数据库&#xff0c;它的数据是存放在内存中&#xff0c;内存有个问题就是关闭服务或者断电会丢失。 Redis的数据也支持写到硬盘中&#xff0c;这个过程就叫做持久化。 Redis提供了2种不同形式的持久化方式。 RDB&#xff08…

安全团队官网介绍页源码

安全团队官网介绍页源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 下载地址 https://www.qqmu.com/2383.html

Unity 角色控制(初版)

角色控制器组件&#xff0c;当然是将组件放在角色上了。 using System.Collections; using System.Collections.Generic; using UnityEngine;public class c1 : MonoBehaviour {// 获取角色控制器private CharacterController player;void Start(){// 加载角色控制器player …

【自然语言处理六-最重要的模型-transformer-下】

自然语言处理六-最重要的模型-transformer-下 transformer decoderMasked multi-head attentionencoder和decoder的连接部分-cross attentiondecoder的输出AT(Autoregresssive)NAT transformer decoder 今天接上一篇文章讲的encoder 自然语言处理六-最重要的模型-transformer-…

红黑树的简单介绍

红黑树 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出俩倍&#x…

爬虫案例二

第一步电影天堂_免费在线观看_迅雷电影下载_电影天堂网 (dytt28.com)电影天堂_电影下载_高清首发 (dytt89.com)电影天堂_免费在线观看_迅雷电影下载_电影天堂网 (dytt28.com) 打开这个网站 我直接打开 requests.exceptions.SSLError: HTTPSConnectionPool(hostwww.dytt28.com…

99.qt qml-单例程序实现

在之前讲过: 58.qt quick-qml系统托盘实现https://nuoqian.blog.csdn.net/article/details/121855993 由于,该示例只是简单讲解了系统托盘实现,并没有实现单例程序,所以多次打开后就会出现多个exe出现的可能,本章出一章QML单例程序实现, 多次打开始终只显示出第一个打开…

论文阅读:2022Decoupled Knowledge Distillation解耦知识蒸馏

SOTA的蒸馏方法往往是基于feature蒸馏的&#xff0c;而基于logit蒸馏的研究被忽视了。为了找到一个新的切入点去分析并提高logit蒸馏&#xff0c;我们将传统的KD分成了两个部分&#xff1a;TCKD和NCKD。实验表明&#xff1a;TCKD在传递和样本难度有关的知识&#xff0c;同时NCK…

【RT-DETR有效改进】全新的SOATA轻量化下采样操作ADown(轻量又涨点,附手撕结构图)

一、本文介绍 本文给大家带来的改进机制是利用2024/02/21号最新发布的YOLOv9其中提出的ADown模块来改进我们的Conv模块&#xff0c;其中YOLOv9针对于这个模块并没有介绍&#xff0c;只是在其项目文件中用到了&#xff0c;我将其整理出来用于我们的YOLOv8的项目&#xff0c;经…

动态之美:Motion 5特效,让视频栩栩如生 mac版

Motion 5&#xff0c;一款强大的视频后期特效软件&#xff0c;凭借其丰富的功能和出色的性能&#xff0c;成为了众多影视制作人员的首 选工具。它不仅能够满足专业级影视制作的需求&#xff0c;也适合初学者探索和实践视频特效的魅力。 Motion 5软件获取 Motion 5拥有丰富多样…

SpringBoot源码解读与原理分析(四十)基于jar/war包的运行机制

文章目录 前言第14章 运行SpringBoot应用14.1 部署打包的两种方式14.1.1 以可独立运行jar包的方式14.1.2 以war包的方式 14.2 基于jar包的独立运行机制14.2.1 可独立运行jar包的相关知识14.2.2 SpringBoot的可独立运行jar包结构14.2.3 JarLauncher的设计及工作原理14.2.3.1 Jar…

怎样获得CNVD原创漏洞证书

1. 前言 因为工作变动&#xff0c;我最近把这一年多的工作挖漏洞的一些工作成果提交到了CNVD漏洞平台&#xff08;https://www.cnvd.org.cn/&#xff09;&#xff0c;获得了多张CNVD原创漏洞证书。本篇博客讲下怎么获得CNVD原创漏洞证书&#xff0c;以供大家参考。 2. CNVD原创…

【设计模式 03】抽象工厂模式

一个具体的工厂&#xff0c;可以专门生产单一某一种东西&#xff0c;比如说只生产手机。但是一个品牌的手机有高端机、中端机之分&#xff0c;这些具体的属于某一档次的产品都需要单独建立一个工厂类&#xff0c;但是它们之间又彼此关联&#xff0c;因为都共同属于一个品牌。我…

数据可视化原理-腾讯-散点图

在做数据分析类的产品功能设计时&#xff0c;经常用到可视化方式&#xff0c;挖掘数据价值&#xff0c;表达数据的内在规律与特征展示给客户。 可是作为一个产品经理&#xff0c;&#xff08;1&#xff09;如果不能够掌握各类可视化图形的含义&#xff0c;就不知道哪类数据该用…