QT:HTTP協議簡單應用
阿新 • • 發佈:2019-01-23
HTTP協議
QNetworkAccessManager
QNetworkReply
QNetworkAccessManager
QNetworkReply
《案例》QT實現HTTP文字瀏覽器
/* HTTP文字瀏覽器 - 程式碼演示 */
// HttpDialog.h #ifndef HTTPDIALOGH #define HTTPDIALOGH #include <QDialog> #include <QNetworkAccessManager > #include <QUrl > #include <QNetworkRequest > #include <QNetworkReply > #include <QAuthenticator > #include <QFile > #include <QFileInfo > namespace Ui { class HttpDialog; } class HttpDialog : public QDialog { Q_OBJECT public: explicit HttpDialog(QWidget *parent = 0); ~HttpDialog(); private slots: //讀取伺服器返回響應資料 void onFinished(QNetworkReply *reply); //驗證登入密碼 void onAuthenticationRequest(QNetworkReply *, QAuthenticator *); //點選連結,處理新的連結 void onAnchorClicked(const QUrl&); //接收響應資料:儲存要下載的檔案 void onReadyRead(); //接收響應資料完畢 void onReplyFinished(); //更新下載進度條, //引數:已經接收的資料大小/期望下載的總資料量 void updateDataReadProgress(qint64,qint64); private: //下載檔案 void downloadFile(const QUrl&); private: Ui::HttpDialog *ui; QNetworkAccessManager *manager;//管理Http請求和響應 //URL(Uniform Resource Locator)統一資源定位符號 QNetworkRequest* request;//請求 QNetworkReply* reply;//響應 QUrl currentUrl;//儲存當前網頁的URL地址,網中每個檔案都有一個獨立的URL QFile *file;//儲存下載的檔案 }; #endif // HTTPDIALOGH
// HttpDialog.cpp #include "HttpDialog.h" #include "ui_HttpDialog.h" HttpDialog::HttpDialog(QWidget *parent) : QDialog(parent), ui(new Ui::HttpDialog) { ui->setupUi(this); //構建QNetworkAccessManager物件 //用於應用程式傳送網路請求和接收網路應答 manager = new QNetworkAccessManager(this); //初始化請求物件 request = new QNetworkRequest(QUrl(" http://code.tarena.com.cn/")); //向Http伺服器傳送請求 manager->get(*request); //隱藏檔案下載進度條 ui->progressBar->hide(); //請求傳送完成,收到伺服器響應傳送finished訊號 //引數即為響應的資料物件 connect(manager,SIGNAL(finished(QNetworkReply*)), this,SLOT(onFinished(QNetworkReply*))); connect(ui->textBrowser,SIGNAL(anchorClicked(QUrl)), this,SLOT(onAnchorClicked(QUrl))); //伺服器返回請求的內容之前,這個訊號被髮射,請求驗證 //在對應的槽函式中填寫密碼和使用者名稱,進行認證 connect(manager, SIGNAL(authenticationRequired(QNetworkReply *, QAuthenticator *)), this, SLOT(onAuthenticationRequest(QNetworkReply *, QAuthenticator *))); } HttpDialog::~HttpDialog() { delete ui; } void HttpDialog::onFinished(QNetworkReply *reply) { qDebug("%s",__func__); //讀取伺服器返回響應資料 QString replyText = reply->readAll(); //顯示到文字瀏覽器介面 ui->textBrowser->setText(replyText); //儲存當前的url currentUrl = reply->url(); } //驗證登入密碼 void HttpDialog::onAuthenticationRequest(QNetworkReply *, QAuthenticator *authenticator){ qDebug("%s",__func__); authenticator->setUser("tarenacode"); authenticator->setPassword("code_2013"); } //點選連結,處理新的連結 void HttpDialog::onAnchorClicked(const QUrl& url){ //qDebug() << url.toString(); //qDebug() << currentUrl.toString(); QUrl newUrl; //處理非".."的連結 if(url.toString() != "../"){ //儲存當前完整的URL newUrl.setUrl(currentUrl.toString() + url.toString()); //如果是下載檔案,則下載該檔案 if(url.toString().indexOf(".tar.gz") != -1 || url.toString().indexOf(".txt") != -1 || url.toString().indexOf(".zip") != -1 || url.toString().indexOf(".doc") != -1 || url.toString().indexOf(".pdf") != -1 || url.toString().indexOf(".rar") != -1) { //qDebug("下載該檔案..."); downloadFile(newUrl); return; } } else{//處理上一級目錄".." //如果已經在頂層目錄,不處理 if(currentUrl.toString() == " http://code.tarena.com.cn/"){ return; } else{//去掉最後一級目錄 //http://code.tarena.com.cn/BIGCode/big1605/ //int length = currentUrl.toString().size(); //倒數第二次出現“/”的位置 int _pos = currentUrl.toString().lastIndexOf("/",-2); //擷取新的字串,去掉最後一級路徑 newUrl = currentUrl.toString().mid(0,_pos+1); //qDebug() << newUrl.toString(); } } manager->get(QNetworkRequest(QUrl(newUrl))); } //下載檔案 void HttpDialog::downloadFile(const QUrl& fileUrl){ qDebug() << fileUrl.toString(); //獲取路徑 //url.path():CSDCode/csd1603/qt/day02.tar.gz //獲取要下載的檔案資訊:檔名 QFileInfo fileInfo(fileUrl.path()); QString fileName(fileInfo.fileName()); //建立檔案 file = new QFile(fileName); if(!file->open(QIODevice::WriteOnly)) { qDebug("file open error"); delete file; file = 0; return; } //傳送獲取檔案請求 reply = manager->get(QNetworkRequest(fileUrl)); //服務收到請求返回資料後相應物件發出readyReady訊號 //onReadyRead()槽函式負責接收資料 connect(reply,SIGNAL(readyRead()),this,SLOT(onReadyRead())); //服務收到請求返回資料後也會產生downloadProgress訊號 //updateDataReadProgress槽函式負責更新進度條 connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(updateDataReadProgress(qint64,qint64))); //應答資訊處理髮送finished()訊號,此時檔案已經下載完成 connect(reply,SIGNAL(finished()), this,SLOT(onReplyFinished())); //設定顯示進度條 ui->progressBar->setValue(0); ui->progressBar->show(); } //接收響應資料完畢(下載完成) void HttpDialog::onReplyFinished() { qDebug("%s",__func__); //隱藏進度條 ui->progressBar->hide(); //重新整理檔案緩衝區,保證資料都已經寫入檔案 file->flush(); //關閉檔案 file->close(); //延後刪除應答物件 reply->deleteLater(); reply = NULL; //刪除檔案指標 delete file; file = NULL; //重新整理介面 QUrl newUrl; int _pos = currentUrl.toString().lastIndexOf("/"); newUrl.setUrl(currentUrl.toString().mid(0,_pos+1)); //qDebug() << newUrl.toString(); manager->get(QNetworkRequest(newUrl)); } //接收應答資料:要下載的檔案 void HttpDialog::onReadyRead() { if(file){ //接收下載的資料並寫到檔案 file->write(reply->readAll()); } } //更新下載進度條, //引數:已經接收的資料大小/期望下載的總資料量 void HttpDialog::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes) { ui->progressBar->setMaximum(totalBytes); ui->progressBar->setValue(bytesRead); }
// main.cpp
#include "HttpDialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
HttpDialog w;
w.show();
return a.exec();
}