Qt之QFtp
来源:互联网 发布:重庆时时彩数据全天 编辑:程序博客网 时间:2024/05/19 22:46
简述
QFtp 类提供了一个 FTP 协议的客户端实现。
该类提供了一个到 FTP 的直接接口,允许对请求有更多的控制。但是,对于新的应用程序,建议使用 QNetworkAccessManager 和 QNetworkReply,因为这些类拥有一个更简单、还更强大的 API。
- 简述
- QFtp
- 工作流程
- 基本使用
- 连接并登录 FTP 服务器
- 切换工作目录
- 列出目录中的内容
- 创建文件夹
- 删除文件目录
- 删除文件
- 删除目录
- 重命名
- 上传文件
- 下载文件
- 连接状态
- 获取当前命令
- 错误处理
- 文件传输模式
- 数据传输类型
QFtp
QFtp 异步工作,因此没有阻塞函数。如果无法立即执行操作,函数仍将立即返回,并且该操作将被调度以供以后执行。调度操作的结果通过信号报告,这种方法依赖于事件循环操作。
可以调度的操作(也被称为“命令”)有:connectToHost()、login()、close()、list()、cd()、get()、put()、remove()、mkdir()、rmdir()、rename() 和 rawCommand()。
所有这些命令都会返回一个唯一的标识符,允许跟踪当前正在执行的命令。当命令的执行开始时,发出带有命令标识符的 commandStarted() 信号。当命令完成时,会发出 commandFinished() 信号,并带有命令标识符和一个 bool 参数,表明该命令在完成时是否出错。
在某些情况下,可能想要执行一系列命令。例如,如果要连接并登录到 FTP 服务器,简单的实现如下:
QFtp *ftp = new QFtp(parent);ftp->connectToHost("192.168.***.***", 21);ftp->login("wang", "123456");
在这种情况下,调度了两个 FTP 命令。当最后一个调度命令完成时,会发出 done() 信号,并带有一个 bool 参数,告诉你序列在完成时是否出错。
如果命令序列中的某个命令的执行期间发生错误,则所有挂起的命令(即:已调度,但尚未执行的命令)会被清除,并且不为它们发射信号。
一些命令,例如 list() ,会发出额外的信号(listInfo())以报告其结果。
对于文件传输,QFtp 可以使用主动或被动模式,并且默认使用被动文件传输模式,可使用 setTransferMode() 设置。
调用 setProxy() 使 QFtp 通过 FTP 代理服务器连接。
函数 hasPendingCommands() 和 clearPendingCommands() 允许查询和清除挂起的命令列表。
如果你在网络方便比较有经验,想要有完整的控制,可以使用 rawCommand() 来执行任意 FTP 命令。
警告:当前版本的 QFtp 不完全支持非 Unix FTP 服务器。
工作流程
如果要从 FTP 服务器下载 /home/wang/ftp.qdoc 文件,可以分为下面几步:
ftp->connectToHost("192.168.***.***", 21); // id == 1ftp->login("wang", "123456"); // id == 2ftp->cd("/home/wang"); // id == 3ftp->get("ftp.qdoc"); // id == 4ftp->close(); // id == 5
流程如下:
- connectToHost() - 指定主机和端口号,连接 FTP 服务器
- login() - 指定用户名和密码,登录到 FTP 服务器
- cd() - 改变服务器的工作目录为 /etc(类似于 Linux 下的命令行:cd /home/wang)
- get() - 从服务器上下载文件 passwd(绝对路径为:/home/wang/ftp.qdoc)
- close() - 关闭到 FTP 服务器的连接
对于该示例,发射以下序列的信号:
commandStarted(1)stateChanged(HostLookup)stateChanged(Connecting)stateChanged(Connected)commandFinished(1, false)commandStarted(2)stateChanged(LoggedIn)commandFinished(2, false)commandStarted(3)commandFinished(3, false)commandStarted(4)dataTransferProgress(0, 8710)dataTransferProgress(8192, 8710)readyRead()dataTransferProgress(8710, 8710)readyRead()commandFinished(4, false)commandStarted(5)stateChanged(Closing)stateChanged(Unconnected)commandFinished(5, false)done(false)
如果要显示进度条以通知用户下载进度,上述示例中的 dataTransferProgress() 信号就会很有用。readyRead() 信号告诉你有数据准备好被读取,然后可以使用 bytesAvailable() 函数查询数据量,并且可以使用 read() 或 readAll() 函数读取数据量。
如果上述示例登录失败(例如:用户名/密码错误),信号将如下所示:
commandStarted(1)stateChanged(HostLookup)stateChanged(Connecting)stateChanged(Connected)commandFinished(1, false)commandStarted(2)commandFinished(2, true)done(true)
然后,可以使用 error() 和 errorString() 函数获取有关错误的详细信息。
基本使用
连接并登录 FTP 服务器
在进行任何操作之前,首先确保有可用的 FTP 服务器,并存在有效的用户(例如:wang),然后连接并登录到 FTP 服务器。
QFtp *ftp = new QFtp(parent);ftp->connectToHost("192.168.***.***", 21); // 主机:192.168.***.*** 端口号:21ftp->login("wang", "123456"); // 用户名:wang 密码:123456
切换工作目录
登录成功之后,默认情况下,服务器的工作目录为用户主目录(例如:/home/wang),可以使用 cd() 来进行更改。例如,切换工作目录为 /home/wang/doc:
ftp->cd("/home/wang/doc");
在进行其他命令操作之前,先一起看看 doc 的树结构。
[wang@localhost doc]$ pwd/home/wang/doc[wang@localhost doc]$ tree.├── c++│ └── qt5_cadaques.pdf├── hello.sh├── linux│ └── linux-program.pdf└── python └── hello.py3 directories, 4 files
里面包含 3 个目录以及 4 个文件。
列出目录中的内容
要列出 dir 目录的内容,可以使用 list(),如果 dir 为空,将列出当前目录的内容。
int QFtp::list(const QString & dir = QString())
对于找到的每个目录条目,都会发出 listInfo() 信号。
// 输出文件详细信息connect(ftp, &QFtp::listInfo, [=](const QUrlInfo &urlInfo) { qDebug() << urlInfo.name() << urlInfo.size() << urlInfo.owner() << urlInfo.group() << urlInfo.lastModified().toString("MMM dd yyyy") << urlInfo.isDir();});ftp->list();
注意:这里只列出文件的一部分信息,其他更多信息请参考 QUrlInfo 。
输出如下:
“c++” 29 “1000” “1000” “十一月 28 2016” true
“hello.sh” 55 “1000” “1000” “十月 20 2016” false
“linux” 30 “1000” “1000” “十一月 28 2016” true
“python” 21 “1000” “1000” “十一月 28 2016” true
可以和服务端比对一下:
[wang@localhost doc]$ ls -l总用量 4drwxrwxr-x. 2 wang wang 29 11月 28 10:41 c++-rw-rw-r--. 1 wang wang 55 10月 20 15:59 hello.shdrwxrwxr-x. 2 wang wang 30 11月 28 10:40 linuxdrwxrwxr-x. 2 wang wang 21 11月 28 10:39 python
创建文件夹
要在服务器上创建一个名为 dir 的目录,使用 mkdir()。
ftp->mkdir("new_dir");
创建完成之后,去服务端验证一下吧!
[wang@localhost doc]$ ls -l | grep new*drwxr-xr-x 2 wang wang 6 11月 28 11:05 new_dir
显然,目录 new_dir 已经创建完成。
删除文件/目录
有创建必然会有删除,没错!remove() 是删除文件,rmdir() 则是删除目录。
删除文件
要从服务器中删除名为 file 的文件,使用 remove()。
ftp->remove("hello.sh"); // 删除文件
删除前:
[wang@localhost doc]$ lsc++ hello.sh linux new_dir python
删除后:
[wang@localhost doc]$ lsc++ linux new_dir python
删除目录
要从服务器中删除名为 dir 的目录,使用 rmdir()。
ftp->rmdir("new_dir"); // 删除空目录ftp->rmdir("c++"); // 删除非空目录
删除前:
[wang@localhost doc]$ tree.├── c++│ └── qt5_cadaques.pdf├── linux│ └── linux-program.pdf├── new_dir└── python └── hello.py4 directories, 3 files
删除后:
[wang@localhost doc]$ tree.├── c++│ └── qt5_cadaques.pdf├── linux│ └── linux-program.pdf└── python └── hello.py3 directories, 3 files
显然,只能删除空目录。如果目录下有文件,则不能删除。
重命名
如果要对文件进行重命名,使用 rename()。
ftp->rename("c++", "c"); // c++ -> c
重命名前:
[wang@localhost doc]$ lsc++ linux python
重命名后:
[wang@localhost doc]$ lsc linux python
上传文件
关于上传文件,有两个重载的函数:
int QFtp::put(QIODevice * dev, const QString & file, TransferType type = Binary)
从 IO 设备 dev 读取数据,并将其写入服务器上名为 file 的文件。从 IO 设备读取数据块,因此此重载允许传输大量数据,而无需立即将所有数据读入内存。
注意:确保 dev 指针在操作期间有效(在发出 commandFinished() 时可以安全地删除它)
m_file = new QFile("E:/Qt.zip");ftp->put(m_file, "Qt.zip");
上传完成后,去服务端查看。
[wang@localhost doc]$ ls -al | grep Qt*-rw-r--r-- 1 wang wang 54246299 11月 28 11:43 Qt.zip
int QFtp::put(const QByteArray & data, const QString & file, TransferType type = Binary)
将给定数据的副本写入服务器上名为 file 的文件。
ftp->put("Hello World!\nI'am a Qter.", "readMe.txt");
上传完成后,去服务端查看。
[wang@localhost doc]$ lsc linux python readMe.txt[wang@localhost doc]$ cat readMe.txt Hello World!I'am a Qter.[wang@localhost doc]$
如果要获取上传的进度,可以关联 dataTransferProgress() 信号。
下载文件
要从服务器下载文件,使用 get()。
int QFtp::get(const QString & file, QIODevice * dev = 0, TransferType type = Binary)
如果 dev 为 0,则当有可用的数据可读时,发出 readyRead() 信号。然后,可以使用 read() 或 readAll() 函数读取数据。
如果 dev 不为 0,则将数据直接写入设备 dev。确保 dev 指针在操作期间有效(在发出commandFinished() 信号时可以安全地删除它)。在这种情况下,readyRead() 信号不发出,你不能用read() 或 readAll() 函数读取数据。
如果你不立即读取数据,它变得可用,即当 readyRead() 信号被发出时,它仍然可用,直到下一个命令开始。
例如,如果要在有可用的数据时向用户提供数据,请连接到 readyRead() 信号并立即读取数据。另一方面,如果只想使用完整的数据,则可以连接到 commandFinished() 信号,并在 get() 命令完成后读取数据。
m_file = new QFile("E:/Qt.zip");if (!m_file->open(QIODevice::WriteOnly)) { m_file->remove(); delete m_file; m_file = NULL;} else { ftp->get("Qt.zip", m_file); // 下载文件}
连接状态
当前的状态 QFtp::State 由 state() 返回 ,当状态改变时,发出 stateChanged() 信号,参数是连接的新状态。该信号通常用于 connectToHost() 或者 close() 命令,也可以“自发地”发射,例如:当服务器意外关闭连接时。
例如,当连接 TCP 服务器的时候,使用一个 QLabel 显示连接的状态信息。
void FtpWindow::stateChanged(int state){ switch (state) { case QFtp::Unconnected: { stateLabel->setText(QStringLiteral("没有连接到主机")); break; } case QFtp::HostLookup: { stateLabel->setText(QStringLiteral("正在进行主机名查找")); break; } case QFtp::Connecting: { stateLabel->setText(QStringLiteral("正在尝试连接到主机")); break; } case QFtp::Connected: { stateLabel->setText(QStringLiteral("已实现与主机的连接")); break; } case QFtp::LoggedIn: { stateLabel->setText(QStringLiteral("已实现连接和用户登录")); break; } case QFtp::Closing: { stateLabel->setText(QStringLiteral("连接正在关闭")); break; } default: break; }}
获取当前命令
currentId() 和 currentCommand() 提供了有关当前执行命令。currentCommand() 返回当前 FTP 的命令类型 QFtp::Command,如果没有命令正在执行,则返回 None。
这允许你对特定命令执行特定操作。例如,在 FTP 客户端中,可能需要在启动 list() 命令时清除目录视图。在这种情况下,可以简单地核查在连接到 commandStarted() 信号的槽函数中 currentCommand() 是否为 List。
void FtpWindow::commandStarted(int id){ QFtp::Command command = ftp->currentCommand(); switch (command) { case QFtp::List: { // 正在执行 list() - 列出目录下的文件 // 清除目录视图 QTreeWidget fileListTree->clear(); break; } default: break; } qDebug() << "commandStarted " << id;}
错误处理
通过 error() 和 errorString() 返回最后一次发生的错误。当接收到 commandFinished() 或者 done() 信号时,如果标识 error 的 bool 参数 为 true,这就非常有用了。
error() 返回的是一个 QFtp::Error 枚举类型,用来标识发生的错误。
注意:如果启动一个新命令,错误的状态会被重置为 NoError。
errorString() 返回的是一个人类可读的字符串。通常是(但不总是)来自服务器的回复,因此并不总是可以翻译字符串。如果消息来自 Qt,则字符串已经通过 tr()。
void FtpWindow::commandFinished(int id, bool error){ Q_UNUSED(id); QFtp::Command command = ftp->currentCommand(); switch (command) { case QFtp::ConnectToHost: { // 连接 FTP 服务器 if (error) { // 发生错误 qDebug() << "Error " << ftp->error() << "ErrorString " << ftp->errorString(); QMessageBox::information(this, "FTP", QStringLiteral("无法连接到 FTP 服务器,请检查主机名是否正确!")); ftp->abort(); ftp->deleteLater(); ftp = NULL; } else { qDebug() << QStringLiteral("登录 FTP 服务器"); } break; } default: break; }}
文件传输模式
枚举 QFtp::TransferMode:
FTP 使用两个套接字连接:一个用于命令,另一个用于发送数据。 虽然命令连接始终由客户端发起,但第二个连接可以由客户端或服务器发起。
此枚举定义客户端(被动模式)还是服务器(活动模式)应设置数据连接。
数据传输类型
枚举 QFtp::TransferType:
此枚举标识使用 get 和 put 命令进行数据传输的类型。
- Qt之QFtp
- Qt之QFtp
- Qt中的QFtp类
- Qt---QFtp上传、下载二进制文件
- QFtp
- Qt中利用QThread在线程中同步使用QFtp
- QT QFtp使用实例 从FTP下载一个文件
- 在Qt中如何实现QThread线程同步QFtp
- Qt编程9:QFtp断点续传(普通文件)
- Qt编程10:QFtp断点续传(文件夹以及文件)
- QFtp学习
- Qt中QFtp获取带有中文的文件名称出现乱码的解决方法
- Qt中QFtp获取带有中文的文件名称出现乱码的解决方法
- 最近在写个自动下载数据的软件,发现QT的QFtp不大好用
- Qt中QFtp和QURL获取带有中文的文件名称出现乱码的解决方法
- QFtp 与中文问题
- QFtp 协议下载
- QFtp的使用
- Oracle单行函数整理
- 添加本地jar到私有maven仓库
- Java内存分配与管理
- Python3.x+requests爬取网站遇到中文乱码的解决方案
- 1123分享总结
- Qt之QFtp
- ubuntu pomelo 新建项目,操作mysql数据库
- Android通知控件
- Excel 多个sheet中的内容合并到一个sheet中
- hibernate的get()和load()介绍二
- 戏说云计算之PaaS,IaaS,SaaS
- Think In Java第一章 对象导论
- Postman安装使用详解
- 上海交大校长张杰院士:大学,重新定义你的人生