1. 程式人生 > >QT:HTTP協議簡單應用

QT:HTTP協議簡單應用

HTTP協議

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();
}