HTTP协议
QNetworkAccessManager
QNetworkReply
《案例》QT实现HTTP文本浏览器
/* HTTP文本浏览器 - 代码演示 */// HttpDialog.h
#ifndef HTTPDIALOGH
#define HTTPDIALOGH
#include
#include
#include
#include
#include
#include
#include
#include
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
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
HttpDialog w;
w.show();
return a.exec();
}