qt4 http

四十二、Qt网络(二)HTTP编程


HTTP即超文本传输协议,它是一种文件传输协议。这一节中我们将讲解如何利用HTTP从网站上下载文件。


下载网页:
private:
    QNetworkAccessManager *manager;
private slots:
    void replyFinished(QNetworkReply *);

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    manager = new QNetworkAccessManager(this);  //新建QNetworkAccessManager对象
    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
    manager->get(QNetworkRequest(QUrl("http://www.yafeilinux.com"))); //发送请求

}


void Widget::replyFinished(QNetworkReply *reply)  //当回复结束后
{

    QTextCodec *codec = QTextCodec::codecForName("utf8");
    QString all = codec->toUnicode(reply->readAll());
   // ui->textBrowser->setText(all);
    ui->textBrowser->setHtml(all);
    reply->deleteLater();   //最后要释放reply对象
}

1.manager = new QNetworkAccessManager(this);  //新建QNetworkAccessManager对象
 2.使用get发送请求连接
manager->get(QNetworkRequest(QUrl("http://www.yafeilinux.com"))); //发送请求
3.在请求完成时,manager会发出信号SIGNAL(finished(QNetworkReply*)),这时执行槽函数replyFinished,将下载到的数据显示出来,以html方式
 ui->textBrowser->setHtml(all);


下载文件
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtNetwork>
#include <QWidget>

namespace Ui {
    class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
        void startRequest(QUrl url); //请求链接
protected:
    //void changeEvent(QEvent *e);
private:
    Ui::Widget *ui;
    QNetworkAccessManager *manager;
    QNetworkReply *reply;
     QUrl url;   //存储网络地址
     QFile *file;  //文件指针
private slots:
    //void replyFinished(QNetworkReply *);
    void on_pushButton_clicked();
    void httpFinished();  //完成下载后的处理
    void httpReadyRead();  //接收到数据时的处理
    void updateDataReadProgress(qint64,qint64); //更新进度条
};

#endif // WIDGET_H

//widget.cpp
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    manager = new QNetworkAccessManager(this);  //新建QNetworkAccessManager对象
   // connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
   // manager->get(QNetworkRequest(QUrl("http://www.yafeilinux.com"))); //发送请求
    ui->progressBar->hide();
}

Widget::~Widget()
{
    delete ui;
}
/*
void Widget::replyFinished(QNetworkReply *reply)  //当回复结束后
{
    QTextCodec *codec = QTextCodec::codecForName("utf8");
    QString all = codec->toUnicode(reply->readAll());
    //ui->textBrowser->setText(all);
    ui->textBrowser->setHtml(all);
    reply->deleteLater();   //最后要释放reply对象
}
*/

void Widget::on_pushButton_clicked()
{
  url = ui->lineEdit->text();
 //获取在界面中输入的url地址,如http://zz.onlinedown.net/down/laolafangkuaijin.rar
    QFileInfo info(url.path());
    QString fileName(info.fileName());
    //获取文件名
    if (fileName.isEmpty()) fileName = "index.html";
//如果文件名为空,则使用“index.html”,
//例如使用“http://www.yafeilinux.com”时,文件名就为空
    file = new QFile(fileName);
    if(!file->open(QIODevice::WriteOnly))
    {   //如果打开文件失败,则删除file,并使file指针为0,然后返回
        qDebug() << "file open error";
        delete file;
        file = 0;
        return;
    }
    startRequest(url);  //进行链接请求
    ui->progressBar->setValue(0);  //进度条的值设为0
    ui->progressBar->show();  //显示进度条
}


void Widget::startRequest(QUrl url)  //链接请求

{

    reply = manager->get(QNetworkRequest(url));
    //下面关联信号和槽
    connect(reply,SIGNAL(finished()),this,SLOT(httpFinished()));
    //下载完成后
    connect(reply,SIGNAL(readyRead()),this,SLOT(httpReadyRead()));
    //有可用数据时
    connect(reply,SIGNAL(downloadProgress(qint64,qint64)),
            this,SLOT(updateDataReadProgress(qint64,qint64)));
    //更新进度条
}


void Widget::httpReadyRead()   //有可用数据

{
    if (file) file->write(reply->readAll());  //如果文件存在,则写入文件
}

void Widget::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
 {
    ui->progressBar->setMaximum(totalBytes); //最大值
    ui->progressBar->setValue(bytesRead);  //当前值
}

void Widget::httpFinished()  //完成下载
{
    ui->progressBar->hide();
    file->flush();
    file->close();
    reply->deleteLater();
    reply = 0;
    delete file;
    file = 0;
}
用到的几个信号
readyRead信号在请求的数据中有新的数据响应的时候产生,什么才算新的数据,一次从外网传输过来一个什么数据包?help没讲---暂时理解刚传过来的某个包属于请求的1部分
finished信号在请求的数据全部返回时产生
downloadProgress信号在..help没讲,可能是定时发生吧

void QHttp::readyRead ( const QHttpResponseHeader & resp ) [signal]

This signal is emitted when there is new response data to read.

If you specified a device in the request where the data should be written to, then this signal is not emitted; instead the data is written directly to the device.

The response header is passed in resp.

You can read the data with the readAll() or read() functions

This signal is useful if you want to process the data in chunks as soon as it becomes available. If you are only interested in the complete data, just connect to the requestFinished() signal and read the data then instead.


void QNetworkReply::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal ) [signal]

This signal is emitted to indicate the progress of the download part of this network request, if there's any. If there's no download associated with this request, this signal will be emitted once with 0 as the value of both bytesReceived and bytesTotal.

The bytesReceived parameter indicates the number of bytes received, while bytesTotal indicates the total number of bytes expected to be downloaded. If the number of bytes to be downloaded is not known, bytesTotal will be -1.

The download is finished when bytesReceived is equal to bytesTotal. At that time, bytesTotal will not be -1.

Note that the values of both bytesReceived and bytesTotal may be different from size(), the total number of bytes obtained through read() or readAll(), or the value of the header(ContentLengthHeader). The reason for that is that there may be protocol overhead or the data may be compressed during the download.


void QNetworkReply::finished () [signal]

This signal is emitted when the reply has finished processing. After this signal is emitted, there will be no more updates to the reply's data or metadata.

Unless close() has been called, the reply will be still be opened for reading, so the data can be retrieved by calls to read() or readAll(). In particular, if no calls to read() were made as a result of readyRead(), a call to readAll() will retrieve the full contents in a QByteArray.

This signal is emitted in tandem with QNetworkAccessManager::finished() where that signal's reply parameter is this object.

Note: Do not delete the object in the slot connected to this signal. Use deleteLater().

You can also use isFinished() to check if a QNetworkReply has finished even before you receive the finished() signal.


1.
manager = new QNetworkAccessManager(this);  //新建QNetworkAccessManager对象
2.
file = new QFile(fileName);//创建文件
reply = manager->get(QNetworkRequest(url));//请求连接
3.
在readyRead信号时,将新的数据写入文件
在downloadProgress信号时,更新进度条
在finished信号时,释放各个资源

可见下载网页和文件都是manager->get来完成的。网页部分是将数据显示在textBrowser,文件部分是将数据存入文件。
并且网页请求可以像下载文件那样每1小部分下载完就显示出来,即在readyRead信号时将收到的部分数据显示出来


下图是wireshark在此次下载网页程序执行时的抓包结果,可以看到http是封装在tcp里面
qt4 http_第1张图片

你可能感兴趣的:(qt4 http)