為了方便網(wǎng)絡(luò)編程,Qt 提供了 Network 模塊。該模塊包含了許多類(lèi),例如:QFtp - 能夠更加輕松使用 FTP 協(xié)議進(jìn)行網(wǎng)絡(luò)編程。
但是,從 Qt5.x 之后,Qt Network 發(fā)生了很大的變化,助手中關(guān)于此部分描述如下:
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.
意思是說(shuō):不再導(dǎo)出 QFtp 和 QUrlInfo 類(lèi),改用 QNetworkAccessManager。
簡(jiǎn)述開(kāi)啟 FTP 服務(wù)效果FtpManager使用更多參考
開(kāi)啟 FTP 服務(wù)
Linux 下實(shí)現(xiàn) FTP 服務(wù)的軟件很多,最常見(jiàn)的有:vsftpd、Wu-ftpd 和 Proftp 等。
訪問(wèn) FTP 服務(wù)器時(shí)需要經(jīng)過(guò)驗(yàn)證,只有經(jīng)過(guò)了 FTP 服務(wù)器的相關(guān)驗(yàn)證,用戶才能訪問(wèn)和傳輸文件。
首先,服務(wù)器需要安裝 FTP 軟件,以 vsftpd 為例:
[root@localhost wang]# which vsftpd
/sbin/vsftpd
1
2這說(shuō)明服務(wù)器已經(jīng)安裝了 vsftpd,再進(jìn)行一系列配置即可使用。
關(guān)于 FTP 服務(wù)的搭建、配置屬于 Linux 范疇,這里就不過(guò)多贅述了,請(qǐng)自行查看資料。
效果實(shí)現(xiàn)效果如下:
如果要獲取更多關(guān)于:文件剩余大小、平均速度、瞬時(shí)速度 、剩余時(shí)間等相關(guān)信息,請(qǐng)參考:Qt之HTTP上傳/下載
FtpManager為了便于使用,封裝一個(gè)簡(jiǎn)單的 FtpManager 管理類(lèi),用于上傳、下載文件。
FTPManager.h
#ifndef FTP_MANAGER
#define FTP_MANAGER
#include
#include
#include
#include
class FtpManager : public QObject
{
Q_OBJECT
public:
explicit FtpManager(QObject *parent = 0);
// 設(shè)置地址和端口
void setHostPort(const QString &host, int port = 21);
// 設(shè)置登錄 FTP 服務(wù)器的用戶名和密碼
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);
// 上傳進(jìn)度
void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
// 下載進(jìn)度
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
private slots:
// 下載過(guò)程中寫(xiě)文件
void finished();
private:
QUrl m_pUrl;
QFile m_file;
QNetworkAccessManager m_manager;
};
#endif // FTP_MANAGER
FTPManager.cpp
#include
#include "FTPManager.h"
FtpManager::FtpManager(QObject *parent)
: QObject(parent)
{
// 設(shè)置協(xié)議
m_pUrl.setScheme("ftp");
}
// 設(shè)置地址和端口
void FtpManager::setHostPort(const QString &host, int port)
{
m_pUrl.setHost(host);
m_pUrl.setPort(port);
}
// 設(shè)置登錄 FTP 服務(wù)器的用戶名和密碼
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)));
}
// 下載過(guò)程中寫(xiě)文件
void FtpManager::finished()
{
QNetworkReply *pReply = qobject_cast(sender());
switch (pReply->error()) {
case QNetworkReply::NoError : {
m_file.write(pReply->readAll());
m_file.flush();
}
break;
default:
break;
}
m_file.close();
pReply->deleteLater();
}
注釋很詳細(xì),我就不再多做解釋了。。。
注意:下載過(guò)程中文件寫(xiě)入是在主線程中進(jìn)行的,如果文件過(guò)大,頻繁寫(xiě)入會(huì)造成主線程卡頓現(xiàn)象。要避免此種情況,請(qǐng)?jiān)诠ぷ骶€程中進(jìn)行。
使用這里,只貼主要代碼:
// 構(gòu)建需要的控件
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("下載"));
// 接信號(hào)槽
connect(pUploadButton, SIGNAL(clicked(bool)), this, SLOT(upload()));
connect(pDownloadButton, SIGNAL(clicked(bool)), this, SLOT(download()));
// 設(shè)置 FTP 相關(guān)信息
m_ftp.setHostPort("192.168.***.***", 21);
m_ftp.setUserInfo("wang", "123456");
其中,m_ftp 是類(lèi)變量 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)));
}
// 更新上傳進(jìn)度
void MainWindow::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
m_pUploadBar->setMaximum(bytesTotal);
m_pUploadBar->setValue(bytesSent);
}
// 更新下載進(jìn)度
void MainWindow::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
m_pDownloadBar->setMaximum(bytesTotal);
m_pDownloadBar->setValue(bytesReceived);
}
// 錯(cuò)誤處理
void MainWindow::error(QNetworkReply::NetworkError error)
{
switch (error) {
case QNetworkReply::HostNotFoundError :
qDebug() << QString::fromLocal8Bit("主機(jī)沒(méi)有找到");
break;
// 其他錯(cuò)誤處理
default:
break;
}
}
在上傳、下載過(guò)程中,確保 Server 端的路徑存在:
[root@localhost wang]# pwd
/home/wang
[root@localhost wang]# ls
hello.sh
[root@localhost wang]#
上傳完成后,可以去 Server 端查看一下:
[root@localhost wang]# ls -l
總用量 52980
-rw-r--r-- 1 root root 20 11月 16 14:01 hello.sh
-rw-r--r-- 1 wang wang 54246299 11月 16 17:36 Qt.zip
[root@localhost wang]# md5sum Qt.zip
8d010354447515d55c65d733bbba2682 Qt.zip
源文件 Qt.zip 的大小為 54,246,299 字節(jié),顯然,目標(biāo)文件也一樣(可使用 MD5 比對(duì),看文件是否損壞),這說(shuō)明已經(jīng)完全上傳成功了。
更多參考 Qt之HTTP上傳/下載原文鏈接:http://blog.csdn.net/liang19890820/article/details/53188182