Qt5移除了QFtp API,原因是其实现质量,QNetworkAccessManager 可以用来提供 ftp url 的上传下载操作; 但是美中不足的是QNetworkAccessManager没有提供list()、cd()、remove()、mkdir()、rmdir()、rename() 和 rawCommand()等操作。
首先封装了类是为了方便调用,减少代码重复:
#ifndef MYFTPMANAGER_H
#define MYFTPMANAGER_H
#include <QUrl>
#include <QObject>
#include <QNetworkReply>
#include <QNetworkAccessManager>
class MyFtpManager : public QObject
Q_OBJECT
public:
explicit MyFtpManager(QObject *parent = 0);
QNetworkReply *put(const QString &localPath, const QString &uploadPath);
QNetworkReply *get(const QString &downloadPath, const QString &localPath);
inline void setPort(int port) { url.setPort(port); }
inline void setHost(const QString &host) { url.setHost(host); }
inline void setPath(const QString &path) { url.setPath(path); }
inline void setUserName(const QString &userName) { url.setUserName(userName); }
inline void setPassword(const QString &password) { url.setPassword(password); }
public slots:
void uploadFinished();
void downloadFinished();
void error(QNetworkReply::NetworkError error);
private:
QUrl url;
QString path;
QNetworkAccessManager manager;
#endif // MYFTPMANAGER_H
#include "MyFtpManager.h"
#include <QFile>
#include <QNetworkRequest>
MyFtpManager::MyFtpManager(QObject *parent) :
QObject(parent)
// 设置协议
url.setScheme("ftp");
QNetworkReply *MyFtpManager::put(const QString &localPath, const QString &uploadPath)
// 文件是否可以打开
QFile file(localPath);
if (!file.open(QIODevice::ReadOnly))
return NULL;
// 设置上传路径
url.setPath(uploadPath);
QNetworkReply *pReply = manager.put(QNetworkRequest(url), file.readAll());
connect(pReply, SIGNAL(finished()), SLOT(uploadFinished()));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
return pReply;
QNetworkReply *MyFtpManager::get(const QString &downloadPath, const QString &localPath)
// 记录要保存的位置
path = localPath;
// 设置下载路径
url.setPath(downloadPath);
QNetworkReply *pReply = manager.get(QNetworkRequest(url));
connect(pReply, SIGNAL(finished()), SLOT(downloadFinished()));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
return pReply;
void MyFtpManager::uploadFinished()
void MyFtpManager::downloadFinished()
QNetworkReply *pReply = qobject_cast<QNetworkReply *>(sender());
if (pReply == NULL)
return;
// 如果有错误就不需要保存
if (pReply->error() != QNetworkReply::NoError)
return;
// 写入文件
QFile file(path);
if (!file.open(QIODevice::WriteOnly))
return;
file.write(pReply->readAll());
file.flush();
file.close();
void MyFtpManager::error(QNetworkReply::NetworkError error)
qDebug() << error;
在MainWnd中声明一个成员变量manager,然后在造函数中初始化它:
manager.setHost("192.168.43.5"); // 设置服务器IP地址
manager.setPort(21); // 设置端口
manager.setUserName("zhangsan"); // 设置用户名
manager.setPassword("000000"); // 设置密码
在点击上传按钮时,把某一个路径下的所有图片都上传到FTP服务器指定的路径下:
void MainWnd::on_tbUpload_clicked()
QDir dir("F:/Pictrue");
QStringList filter;
filter << "*.jpg" << "*.bmp" << "*.png";
QList<QFileInfo> list = QList<QFileInfo>(dir.entryInfoList(filter));
foreach (QFileInfo info, list)
QNetworkReply *pReply = manager.put(info.filePath(), QString("/picture/%1").arg(info.fileName()));
connect(pReply, SIGNAL(uploadProgress(qint64,qint64)), SLOT(uploadProgress(qint64,qint64)));
在点击下载按钮时,只是单纯的下载某一张图像到程序根目录:
void MainWnd::on_tbDownload_clicked()
QNetworkReply *pReply = manager.get("/picture/DSCF21061.jpg", "./DSCF21061.jpg");
connect(pReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(downloadProgress(qint64,qint64)));
然后就是通过信号槽更新进度条:
void MainWnd::uploadProgress(qint64 byteSend, qint64 byteTotal)
ui->pgbUpload->setMaximum(byteTotal);
ui->pgbUpload->setValue(byteSend);
void MainWnd::downloadProgress(qint64 byteSend, qint64 byteTotal)
ui->pgbDownload->setMaximum(byteTotal);
ui->pgbDownload->setValue(byteSend);
1. 使用QUrl时需要设置'ftp'协议,否则会提示以下的错误:
2. 在点击上传时,要上传的目录必须存在,也就是说这里上传的目录"/picture"是事先在服务器创建好的;如果服务器中不存在这个目录它不会主动帮你创建,会提示以下的错误:
QNetworkReply::NetworkError(ContentAccessDenied)
源码下载1(折扣):https://item.taobao.com/item.htm?ft=t&id=702584276003
源码下载2(无折扣):https://download.csdn.net/download/Ilson_/19418875
Windows下FTP服务器搭建:https://blog.csdn.net/Ilson_/article/details/97818689
QFtp在客户端实现给服务器一次性创建多级目录:https://blog.csdn.net/Ilson_/article/details/98654137
QFtp实现文件上传、下载、新建文件夹、重命名、删除和刷新等功能:https://blog.csdn.net/Ilson_/article/details/98371848
Qt5移除了QFtp API,原因是其实现质量,QNetworkAccessManager可以用来提供ftpurl的上传下载操作; 但是美中不足的是QNetworkAccessManager没有提供list()、cd()、remove()、mkdir()、rmdir()、rename() 和 rawCommand()等操作。 先来看看操作结果: ...
本来是打算用新的类QNetworkAccessManager实现的客户端的文件上传、下载、新建文件夹、重命名、删除和刷新等功能,但是QNetworkAccessManager没有提供原本在QFtp提供的list()、cd()、remove()、mkdir()、rmdir()、rename() 和 rawCommand()等操作,所以无奈之下只能选用了旧版本的QFtp来实现,毕竟既然官方都废弃了QFtp而选用QNetworkAccessManager来代替,那肯定是后者比前者更加可靠稳定。
虽然QFtp在Qt5.0之后就被官方移除了,但是其基本功能还是挺全的,虽然在上传下载文件的时候带中文时会乱码,但也是能解决的。
最近在做一个项目也是用到了QFtp上传文件到别人的服务器,突然就想到了要做一个简单的客户端实现其基本的功能,于是在闲暇时就慢慢的把功能给加上去了,虽然有点简陋但是还是实现了有不少的功能,当然也包括了前面提到上传下载带中文的文件乱码问题。
从QT5之后,访问FTP服务器就没有了QFtp,都是使用QNetworkAccessManager访问FTP,其代码和访问HTTP服务器是差不多的,只是在设置url时需要添加用户名密码以及端口号,不多说上代码。
#ifndef FTPCLIENT_H
#define FTPCLIENT_H
#include <QObject>
#include <QNetwork...
因为项目需要,第一次接触到FTP的上传问题,经过查阅后摈弃了旧的QFtp,采用新的QNetworkAccessManager。有关它的使用其实也很方便,已经提供了比较成熟的接口和信号,下面总结一下。首先,在头文件创建一些变量和指针
url是之后需要上传的FTP服务器文件路径;QNetworkAccessManager 就是所谓的网络访问管理器,主要靠它来进行文件上传;QNetworkReply 是QNetworkAccessManager 上传时的一个回复对象,可以通过它来得到一些返回的信息然后,是cpp文
前文已经介绍了Qt项目中实现FTP上传文件的三种实现方式,今天主要看QFtp的实现,以及接口在使用过程中需要注意的问题避坑。
首先我们要知道ftp服务器端的IP地址,以及端口号,前面我们介绍到FTP协议有两种方式,主动模式和被动模式(这里不做过多介绍,感兴趣的可以去查阅相关资料),通常开发都是使用被动模式,这种比较简单,由服务器端默认端口地址为21,客户端连接。
接着需要登录ftp的账号和密码,知道这几个数据后就可以连接服务器了。
我们看一下相关接口:
QFtp ftp;
ftp.connect
Qt是一种功能强大的跨平台应用程序框架,包含很多内置类和函数库,其中QNetworkAccessManager是Qt中处理网络请求的重要类。此外,QNetworkAccessManager还可以用于实现FTP协议。
首先,需要创建一个QNetworkAccessManager对象,并使用QUrl类来表示FTP服务器的URL地址。然后,调用QNetworkAccessManager类的get函数来向FTP服务器发送请求。在这里,可以通过QNetworkRequest类的setUrl函数来设置请求URL。
下载文件时,可以使用reply()函数获取服务器响应,并使用QFile类打开本地文件,最后使用QIODevice::write()函数来写入文件。
上传文件时,可以使用QNetworkRequest类的setHeader函数来设置上传文件的元数据信息,如文件名和文件大小等。然后,使用QFile类打开本地文件,并使用QHttpMultiPart类将文件内容添加到请求体中。最后,调用QNetworkAccessManager类的post函数发送请求,并使用reply()函数获取服务器响应。
总之,Qt中QNetworkAccessManager提供了完整的FTP访问功能,可以方便地实现FTP上传和下载文件操作,并且具有很好的跨平台性。