Qt之FTP上传/下载

来源:互联网 发布:versions for mac使用 编辑:程序博客网 时间:2024/05/11 23:46

文章转载:http://blog.csdn.net/liang19890820/article/details/53188182


简述

为了方便网络编程,Qt 提供了 Network 模块。该模块包含了许多类,例如:QFtp - 能够更加轻松使用 FTP 协议进行网络编程。

但是,从 Qt5.x 之后,Qt Network 发生了很大的变化,助手中关于此部分描述如下:

The QFtp and QUrlInfo classes are no longer exported. Use QNetworkAccessManager instead. Programs that require raw FTP or HTTP streams can use the Qt FTP and Qt HTTP compatibility add-on modules that provide the QFtp and QHttp classes as they existed in Qt 4.

意思是说:不再导出 QFtp 和 QUrlInfo 类,改用 QNetworkAccessManager。

  • 简述
  • 开启 FTP 服务
  • 效果
  • FtpManager
  • 使用
  • 更多参考

开启 FTP 服务

Linux 下实现 FTP 服务的软件很多,最常见的有:vsftpd、Wu-ftpd 和 Proftp 等。

访问 FTP 服务器时需要经过验证,只有经过了 FTP 服务器的相关验证,用户才能访问和传输文件。

首先,服务器需要安装 FTP 软件,以 vsftpd 为例:

[root@localhost wang]# which vsftpd/sbin/vsftpd
  • 1
  • 2
  • 1
  • 2

这说明服务器已经安装了 vsftpd,再进行一系列配置即可使用。

关于 FTP 服务的搭建、配置属于 linux 范畴,这里就不过多赘述了,请自行查看资料。

效果

实现效果如下:

这里写图片描述

如果要获取更多关于:文件剩余大小、平均速度、瞬时速度 、剩余时间等相关信息,请参考:Qt之HTTP上传/下载

FtpManager

为了便于使用,封装一个简单的 FtpManager 管理类,用于上传、下载文件。

FTPManager.h

#ifndef FTP_MANAGER#define FTP_MANAGER#include <QUrl>#include <QFile>#include <QNetworkReply>#include <QNetworkAccessManager>class FtpManager : public QObject{    Q_OBJECTpublic:    explicit FtpManager(QObject *parent = 0);    // 设置地址和端口    void setHostPort(const QString &host, int port = 21);    // 设置登录 FTP 服务器的用户名和密码    void setUserInfo(const QString &userName, const QString &password);    // 上传文件    void put(const QString &fileName, const QString &path);    // 下载文件    void get(const QString &path, const QString &fileName);signals:    void error(QNetworkReply::NetworkError);    // 上传进度    void uploadProgress(qint64 bytesSent, qint64 bytesTotal);    // 下载进度    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);private slots:    // 下载过程中写文件    void finished();private:    QUrl m_pUrl;    QFile m_file;    QNetworkAccessManager m_manager;};#endif // FTP_MANAGER
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

FTPManager.cpp

#include <QFileInfo>#include "FTPManager.h"FtpManager::FtpManager(QObject *parent)    : QObject(parent){    // 设置协议    m_pUrl.setScheme("ftp");}// 设置地址和端口void FtpManager::setHostPort(const QString &host, int port){    m_pUrl.setHost(host);    m_pUrl.setPort(port);}// 设置登录 FTP 服务器的用户名和密码void FtpManager::setUserInfo(const QString &userName, const QString &password){    m_pUrl.setUserName(userName);    m_pUrl.setPassword(password);}// 上传文件void FtpManager::put(const QString &fileName, const QString &path){    QFile file(fileName);    file.open(QIODevice::ReadOnly);    QByteArray data = file.readAll();    m_pUrl.setPath(path);    QNetworkReply *pReply = m_manager.put(QNetworkRequest(m_pUrl), data);    connect(pReply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64)));    connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SIGNAL(error(QNetworkReply::NetworkError)));}// 下载文件void FtpManager::get(const QString &path, const QString &fileName){    QFileInfo info;    info.setFile(fileName);    m_file.setFileName(fileName);    m_file.open(QIODevice::WriteOnly | QIODevice::Append);    m_pUrl.setPath(path);    QNetworkReply *pReply = m_manager.get(QNetworkRequest(m_pUrl));    connect(pReply, SIGNAL(finished()), this, SLOT(finished()));    connect(pReply, SIGNAL(downloadProgress(qint64, qint64)), this, SIGNAL(downloadProgress(qint64, qint64)));    connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SIGNAL(error(QNetworkReply::NetworkError)));}// 下载过程中写文件void FtpManager::finished(){    QNetworkReply *pReply = qobject_cast<QNetworkReply *>(sender());    switch (pReply->error()) {    case QNetworkReply::NoError : {        m_file.write(pReply->readAll());        m_file.flush();    }        break;    default:        break;    }    m_file.close();    pReply->deleteLater();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

注释很详细,我就不再多做解释了。。。

注意:下载过程中文件写入是在主线程中进行的,如果文件过大,频繁写入会造成主线程卡顿现象。要避免此种情况,请在工作线程中进行。

使用

这里,只贴主要代码:

// 构建需要的控件QPushButton *pUploadButton = new QPushButton(this);QPushButton *pDownloadButton = new QPushButton(this);m_pUploadBar = new QProgressBar(this);m_pDownloadBar = new QProgressBar(this);pUploadButton->setText(QString::fromLocal8Bit("上传"));pDownloadButton->setText(QString::fromLocal8Bit("下载"));// 接信号槽connect(pUploadButton, SIGNAL(clicked(bool)), this, SLOT(upload()));connect(pDownloadButton, SIGNAL(clicked(bool)), this, SLOT(download()));// 设置 FTP 相关信息m_ftp.setHostPort("192.168.***.***", 21);m_ftp.setUserInfo("wang", "123456");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

其中,m_ftp 是类变量 FtpManager。

// 上传文件void MainWindow::upload(){    m_ftp.put("E:\\Qt.zip", "/home/wang/Qt.zip");    connect(&m_ftp, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));    connect(&m_ftp, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64)));}// 下载文件void MainWindow::download(){    m_ftp.get("/home/wang/Qt.zip", "F:\\Qt.zip");    connect(&m_ftp, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));    connect(&m_ftp, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));}// 更新上传进度void MainWindow::uploadProgress(qint64 bytesSent, qint64 bytesTotal){    m_pUploadBar->setMaximum(bytesTotal);    m_pUploadBar->setValue(bytesSent);}// 更新下载进度void MainWindow::downloadProgress(qint64 bytesReceived, qint64 bytesTotal){    m_pDownloadBar->setMaximum(bytesTotal);    m_pDownloadBar->setValue(bytesReceived);}// 错误处理void MainWindow::error(QNetworkReply::NetworkError error){    switch (error) {    case QNetworkReply::HostNotFoundError :        qDebug() << QString::fromLocal8Bit("主机没有找到");        break;        // 其他错误处理    default:        break;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

在上传、下载过程中,确保 Server 端的路径存在:

[root@localhost wang]# pwd/home/wang[root@localhost wang]# lshello.sh[root@localhost wang]#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

上传完成后,可以去 Server 端查看一下:

[root@localhost wang]# ls -l总用量 52980-rw-r--r-- 1 root root       20 1116 14:01 hello.sh-rw-r--r-- 1 wang  wang  54246299 1116 17:36 Qt.zip[root@localhost wang]# md5sum Qt.zip 8d010354447515d55c65d733bbba2682  Qt.zip
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

源文件 Qt.zip 的大小为 54,246,299 字节,显然,目标文件也一样(可使用 MD5 比对,看文件是否损坏),这说明已经完全上传成功了。