[Qt教程] 第32篇 網絡(二)HTTP
樓主
發表於 2013-8-28 17:21:28 | 查看:
637| 回複: 8

HTTP
版權聲明
該文章原創於作者yafeilinux,轉載請注明出處! 導語 HTTP(HyperText Transfer Protocol,超文本傳輸協議)是一個客戶端和服務器端請求和應答的標準。在Qt的網絡模塊中提供了網絡訪問接口來實現HTTP編程。網絡訪問接口是執行一般的網絡操作的類的集合,該接口在特定的操作和使用的協議(例如,通過HTTP進行獲取和發送數據)上提供了一個抽象層,隻為外部暴露出了類、函數和信號。 上一節中我們已經提到過了,現在Qt中使用QNetworkAccessManager類和QNetworkReply類來進行HTTP的編程。網絡請求由QNetworkRequest類來表示,它也作為與請求有關的信息(例如,任何頭信息和使用加密)的容器。在創建請求對象時指定的URL決定了請求使用的協議,目前支持HTTP、FTP和本地文件URLs的上傳和下載。QNetworkAccessManager類用來協調網絡操作,每當一個請求創建後,該類用來調度它,並發射信號來報告進度。該類還協調cookies的使用,身份驗證請求,及其代理的使用等。對於網絡請求的應答使用QNetworkReply類表示,它會在請求被完成調度時由QNetworkAccessManager來創建。QNetworkReply提供的信號可以用來單獨的監視每一個應答。
下麵我們先講解一個簡單下載網頁的例子,然後將其擴展為可以下載任何文件。
環境:Windows Xp + Qt 4.8.5+Qt Creator 2.8.0 目錄 一、簡單的網頁瀏覽功能 二、實現下載文件功能
正文 一、簡單的網頁瀏覽功能 1.新建Qt Gui應用,項目名稱為http,基類使用默認的QMainWindow即可,類名為MainWindow。 2.完成後打開http.pro文件,然後添加下麵一行代碼來使用網絡模塊: QT += network
然後保存該文件。
3.下麵打開mainwindow.ui文件進入設計模式,向界麵上添加一個Text Browser部件。效果如下圖所示。 ![]() 4.打開mainwindow.h文件,先包含頭文件:#include <QtNetwork>
然後添加一個private私有對象定義:QNetworkAccessManager
*manager;
最後添加一個私有槽聲明:
private slots:
void replyFinished(QNetworkReply *);
5.下麵到mainwindow.cpp文件中,先在構造函數中添加如下代碼: manager = new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply*)),
this,SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("https://www.qter.org")));
這裏先創建了一個QNetworkAccessManager類的實例,它用來發送網絡請求和接收應答。然後關聯了管理器的finished()信號和我們自定義的槽,每當網絡應答結束時都會發射這個信號。最後使用了get()函數來發送一個網絡請求,網絡請求使用QNetworkRequest類表示,get()函數返回一個QNetworkReply對象。除了get()函數,管理器還提供了發送HTTP POST請求的post()函數。 6.下麵添加槽的定義: void MainWindow::replyFinished(QNetworkReply *reply)
{
QTextCodec *codec = QTextCodec::codecForName("utf8");
QString all = codec->toUnicode(reply->readAll());
ui->textBrowser->setText(all);
reply->deleteLater();
}
因為QNetworkReply繼承自QIODevice類,所以可以操作一般的I/O設備一樣來操作該類。這裏使用了readAll()函數來讀取所有的應答數據,為了正常顯示中文,使用了QTextCodec類來轉換編碼。在完成數據的讀取後,需要使用deleteLater()來刪除replay對象。 7.因為這裏使用了QtextCodec類,所以還需要在mainwindow.cpp文件中包含頭文件 #include <QTextCodec>
下麵運行程序,效果如下圖所示。
![]() 這裏再將整個過程簡答敘述一遍:上麵實現了最簡單的應用HTTP協議下載網頁的功能。QNetworkAccessManager類用於發送網絡請求和接受回複,具體來說,它是用QNetworkRequest 類來管理請求,QNetworkReply類進行接收回複,並對數據進行處理。 在上麵的代碼中,我們使用了下麵的代碼來發送請求:
manager->get(QNetworkRequest(QUrl("https://www.qter.org"))); 它返回一個QNetworkReply對象,這個後麵再講。我們隻需知道隻要發送請求成功,它就會下載數據。而當數據下載完成後,manager會發出finished()信號,我們關聯了該信號: connect(manager, SIGNAL(finished(QNetworkReply*)), this,SLOT(replyFinished(QNetworkReply*)));
也就是說,當下載數據結束時,就會執行replyFinished()函數。在這個函數中我們對接收的數據進行處理: QTextCodec *codec = QTextCodec::codecForName("utf8"); QString all = codec->toUnicode(reply->readAll());
ui->textBrowser->setText(all);
這裏,為了能顯示下載的網頁中的中文,我們使用了QTextCodec 類對象,應用utf8編碼。使用reply->readAll()函數就可以將下載的所有數據讀出。然後,我們在textBrowser中將數據顯示出來。當reply對象已經完成了它的功能時,我們需要將它釋放,就是最後一條代碼: reply->deleteLater();
二、實現下載文件功能 通過上麵的例子可以看到,Qt中編寫基於HTTP協議的程序是十分簡單的,隻有十幾行代碼。不過,一般我們下載文件都想要看到下載進度。下麵我們就更改上麵的程序,讓它可以下載任意的文件,並且顯示下載進度。 1.進入設計模式,刪除以前的Text Browser部件,然後拖入一個Line Edit,一個Label,一個Progress Bar和一個Push Button,設計界麵如下圖所示。 ![]() 2. 在寫代碼之前,我們先介紹一下整個程序執行的流程:開始我們先讓進度條隱藏。當我們在Line Edit中輸入下載地址,點擊下載按鈕後,我們應用輸入的下載地址,獲得文件名,在磁盤上新建一個文件,用於保存下載的數據,然後進行鏈接,並顯示進度條。在下載過程中,我們將每次獲得的數據都寫入文件中,並更新進度條,在接收完文件後,我們重新隱藏進度條,並做一些清理工作。根據這個思路,我們開始代碼的編寫。 3.到mainwindow.h中,首先添加public函數聲明:
void startRequest(QUrl url); //請求鏈接
然後添加幾個private變量和對象定義: QNetworkReply *reply;
QUrl url; //存儲網絡地址
QFile *file; //文件指針
最後到private slots中,刪除前麵的replyFinished(QNetworkReply *)槽聲明,並添加如下代碼: private slots:
void on_pushButton_clicked(); //下載按鈕的單擊事件槽函數
void httpFinished(); //完成下載後的處理
void httpReadyRead(); //接收到數據時的處理
void updateDataReadProgress(qint64, qint64); //更新進度條
4. 下麵到mainwindow.cpp文件中,將前麵在構造函數中添加的內容刪除,然後添加如下代碼: manager = new QNetworkAccessManager(this);
ui->progressBar->hide();
我們在構造函數中先隱藏進度條。等開始下載時再顯示它。
5. 下麵將前麵程序中添加的replyFinished()函數的定義刪除,然後添加新的函數的定義。先添加網絡請求函數的實現: void MainWindow::startRequest(QUrl url)
{
reply = manager->get(QNetworkRequest(url));
connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
connect(reply, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(updateDataReadProgress(qint64, qint64)));
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
}
這裏使用了get()函數來發送網絡請求,然後進行了QNetworkReply對象的幾個信號和自定義槽的關聯。其中readyRead()信號繼承自QIODevice類,每當有新的數據可以讀取時,都會發射該信號;每當網絡請求的下載進度更新時都會發射downloadProgress()信號,它用來更新進度條;每當應答處理結束時,都會發射finished()信號,該信號與前麵程序中QNetworkAccessManager類的finished()信號作用相同,隻不過是發送者不同,參數也不同而已。下麵添加幾個槽的定義。 void MainWindow::httpReadyRead()
{
if (file) file->write(reply->readAll());
}
這裏先判斷是否創建了文件,如果是,則讀取返回的所有數據,然後寫入到文件。該文件是在後麵的“下載”按鈕單擊信號槽中創建並打開的。 void MainWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesRead);
}
這裏設置了一下進度條的最大值和當前值。 void MainWindow::httpFinished()
{
ui->progressBar->hide();
file->flush();
file->close();
reply->deleteLater();
reply = 0;
delete file;
file = 0;
}
當完成下載後,重新隱藏進度條,然後刪除reply和file對象。下麵是“下載”按鈕的單擊信號的槽: void MainWindow::on_pushButton_clicked()
{
url = ui->lineEdit->text();
QFileInfo info(url.path());
QString fileName(info.fileName());
if (fileName.isEmpty()) fileName = "index.html";
file = new QFile(fileName);
if(!file->open(QIODevice::WriteOnly))
{
qDebug() << "file open error";
delete file;
file = 0;
return;
}
startRequest(url);
ui->progressBar->setValue(0);
ui->progressBar->show();
}
這裏使用要下載的文件名創建了本地文件,然後使用輸入的url進行了網絡請求,並顯示進度條。 完成後,可以嚐試輸入一個文件的下載地址,比如這裏輸入了《Qt Creator快速入門》一書在百度網盤上的地址,效果如下圖所示。 ![]() 7.最後,可以去項目編譯生成的文件目錄中查看下載的文件(我這裏是E:\http-build-桌麵-Debug),可以看到下載的文件,如下圖所示。 ![]() 結語 HTTP應用的內容就講到這裏,可以看到它是很容易的,也不需要大家了解太多的HTTP的原理知識。關於相關的類的其他使用,也可以查看其幫助文檔。在上麵的例子中,我們隻是為了講解知識,所以程序不是很完善,對於一個真正的工程,還是需要注意更多其他細節的,大家可以查看一下Qt演示程序HTTP Client的源代碼。 涉及到的源碼: ![]() |
最後更新:2017-04-03 14:54:11
上一篇:
在頁麵中 js 獲取光標/鼠標的坐標,獲取光標的的像素坐標
下一篇:
DirectDraw讀書筆記
第六章 C++模板
weblogic中設置數據源的注意點
Jsp中使用絕對路徑${pageContext.request.contextPath }
Oracle數據庫的用戶管理
局域網【快三單雙群111·1276】傳輸數據
雲服務器 ECS 建站教程:Discuz安裝教程
雲原生(Cloud Native)- 移動App研發新範式
Database Recovery in GitLab – Implementing Database Disaster Tolerance & High Availability
IE8市場份額跌至25%以下 火狐15份額突破10%
QT Mobile: 一統IOS/Andriod/WP/等移動平台的江湖