14-5_Qt 5.9 C++开发指南_基于HTTP 协议的网络应用程序

文章目录

  • 1. 实现高层网络操作的类
  • 2. 基于HTTP协议的网络文件下载
  • 3.源码
    • 3.1 可是化UI设计
    • 3.2 mainwindow.h
    • 3.3 mainwindow.cpp

1. 实现高层网络操作的类

Qt 网络模块提供一些类实现 OSI 7 层网络模型中高层的网络协议,如 HTTP、FTP、SNMP等,这些类主要是 QNetworkRequest、QNetworkReply和QNetworkAccessManager。

QNetworkRequest 类通过一个URL 地址发起网络协议请求,也保存网络请求的信息,目前支持 HTTP、FTP 和局部文件 URLs的下载或上传。
QNetworkAccessManager 类用于协调网络操作。在 QNetworkRequest 发起一个网络请求后,
QNetworkAccessManager 类负责发送网络请求,创建网络响应。

QNetworkReply 类表示网络请求的响应。由 QNetworkAccessManager 在发送一个网络请求后创建一个网络响应。QNetworkReply 提供的信号 finished()、readyRead()和 downloadProgress()可以监测网络响应的执行情况,执行相应操作。
QNetworkReply 是QIODevice 的子类,所以QNetworkReply 支持流读写功能,也支持异步或同步工作模式

2. 基于HTTP协议的网络文件下载

基于上述三个类,设计一个基于HTTP 协议的网络文件下载程序,实例程序名称 samp14_5,图 14-12 是程序运行下载文件时的界面。

在这里插入图片描述

在 URL 地址编辑框里输入一个网络文件 URL 地址,设置下载文件保存路径后,单击“下载按钮就可以开始下载文件到设置的目录下。进度条可以显示文件下载进度,下载完成后还可以用缺省的软件打开下载的文件。URL 里的 HTTP 地址可以是任何类型的文件,如 html、pdf、doc、exe 等。
实例 samp14_5主界面是基于 QMainWindow 的窗口类 MainWindow,使用 UI设计器设计界面,删除了主窗口上的工具栏和状态栏。MainWindow 类的定义如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    <QMainWindow>
#include    <QNetworkAccessManager>
#include    <QNetworkReply>
#include    <QFile>
#include    <QUrl>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    QNetworkAccessManager networkManager;//网络管理
    QNetworkReply *reply;   //网络响应
    QFile *downloadedFile;//下载保存的临时文件
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
//自定义槽函数
    void on_finished();
    void on_readyRead();
    void on_downloadProgress(qint64 bytesRead, qint64 totalBytes);
...

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

要下载文件,先在窗口上的 URL编辑框里输入下载地址(可以使用 Ctrl+V 组合键粘贴URL地址),再设置下载文件保存的目录。单击“缺省路径”按钮会在程序的当前目录下创建一个临时文件夹,代码如下:

void MainWindow::on_btnDefaultPath_clicked()
{//缺省路径  按钮
    QString  curPath=QDir::currentPath();
    QDir    dir(curPath);

    QString  sub="temp";
    dir.mkdir(sub);

    ui->editPath->setText(curPath+"/"+sub+"/");
}

输入这些设置后,单击“下载”按钮开始下载过程,“下载”按钮的响应代码如下:

void MainWindow::on_btnDownload_clicked()
{//开始下载 按钮
    QString urlSpec = ui->editURL->text().trimmed();
    if (urlSpec.isEmpty())
    {
        QMessageBox::information(this, "错误",
          "请指定需要下载的URL");
        return;
    }

    QUrl newUrl = QUrl::fromUserInput(urlSpec);//URL地址
    if (!newUrl.isValid())
    {
        QMessageBox::information(this, "错误",
          QString("无效URL: %1 \n 错误信息: %2").arg(urlSpec, newUrl.errorString()));
        return;
    }

    QString tempDir =ui->editPath->text().trimmed();//临时目录
    if (tempDir.isEmpty())
    {
        QMessageBox::information(this, tr("错误"), "请指定保存下载文件的目录");
        return;
    }

    QString fullFileName =tempDir+newUrl.fileName(); //文件名

    if (QFile::exists(fullFileName))
        QFile::remove(fullFileName);

    downloadedFile =new QFile(fullFileName);//创建临时文件
    if (!downloadedFile->open(QIODevice::WriteOnly))
    {
        QMessageBox::information(this, tr("错误"),"临时文件打开错误");
        return;
    }

    ui->btnDownload->setEnabled(false);

//发送玩过请求,创建网络响应
    reply = networkManager.get(QNetworkRequest(newUrl));
    connect(reply, SIGNAL(finished()), this, SLOT(on_finished()));
    connect(reply, SIGNAL(readyRead()), this, SLOT(on_readyRead()));
    connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
            this, SLOT(on_downloadProgress(qint64,qint64)));
}

代码在读取 URL 地址后,将其转换为一个 QUrl 类变量 newUrl,并检查其有效性,再检查临时文件目录,创建临时文件 downloadedFile。

这些准备好之后,用QNetworkAccessManager 发布网络请求,请求下载URL 地址表示的文件,并创建网络响应,关键代码为:

reply = networkManager.get(QNetworkRequest(newUrl));

reply 为网络响应,将其 3 个信号与相关的自定义槽函数相关联,实现相应的操作。这3 个槽函数的代码如下:

void MainWindow::on_readyRead()
{//读取下载的数据
    downloadedFile->write(reply->readAll());
}

void MainWindow::on_downloadProgress(qint64 bytesRead, qint64 totalBytes)
{//下载进程
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesRead);
}

void MainWindow::on_finished()
{//网络响应结束
    QFileInfo fileInfo;
    fileInfo.setFile(downloadedFile->fileName());

    downloadedFile->close();
    delete downloadedFile;
    downloadedFile = Q_NULLPTR;

    reply->deleteLater(); //
    reply = Q_NULLPTR;

    if (ui->checkOpen->isChecked())//打开下载的文件
        QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));

    ui->btnDownload->setEnabled(true);
}


在缓冲区有新下载的数据等待读取时,会发射 readyRead()信号,槽函数 on_readyRead()读取下载缓冲区的数据到临时文件。
downloadProgress()是表示网络操作进度的信号,传递 bytesRead 和 totalBytes 两个参数,表示已读取字节数和总的字节数;on_downloadProgress()槽函数将这两个参数用于进度条的显示,可以显示下载进度。
finished()信号在下载结束后发射,槽函数 on_finished()的功能是关闭临时文件,删除文件变量和网络响应变量。然后用 QDesktopServices:openUrl()函数调用缺省的应用软件打开下载的文件,例如,如果下载的是一个 PDF 文件,会自动用相关联的 PDF 阅读器软件打开此文件。

3.源码

3.1 可是化UI设计

在这里插入图片描述

3.2 mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    <QMainWindow>
#include    <QNetworkAccessManager>
#include    <QNetworkReply>
#include    <QFile>
#include    <QUrl>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    QNetworkAccessManager networkManager;//网络管理
    QNetworkReply *reply;   //网络响应
    QFile *downloadedFile;//下载保存的临时文件
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
//自定义槽函数
    void on_finished();
    void on_readyRead();
    void on_downloadProgress(qint64 bytesRead, qint64 totalBytes);


    void on_btnDefaultPath_clicked();

    void on_btnDownload_clicked();

    void on_editURL_textChanged(const QString &arg1);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

3.3 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include    <QDir>
#include    <QMessageBox>
#include    <QDesktopServices>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->editURL->setClearButtonEnabled(true);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_finished()
{//网络响应结束
    QFileInfo fileInfo;
    fileInfo.setFile(downloadedFile->fileName());

    downloadedFile->close();
    delete downloadedFile;
    downloadedFile = Q_NULLPTR;

    reply->deleteLater(); //
    reply = Q_NULLPTR;

    if (ui->checkOpen->isChecked())//打开下载的文件
        QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));

    ui->btnDownload->setEnabled(true);
}

void MainWindow::on_readyRead()
{//读取下载的数据
    downloadedFile->write(reply->readAll());
}

void MainWindow::on_downloadProgress(qint64 bytesRead, qint64 totalBytes)
{//下载进程
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesRead);
}

void MainWindow::on_btnDefaultPath_clicked()
{//缺省路径  按钮
    QString  curPath=QDir::currentPath();
    QDir    dir(curPath);

    QString  sub="temp";
    dir.mkdir(sub);

    ui->editPath->setText(curPath+"/"+sub+"/");
}

void MainWindow::on_btnDownload_clicked()
{//开始下载 按钮
    QString urlSpec = ui->editURL->text().trimmed();
    if (urlSpec.isEmpty())
    {
        QMessageBox::information(this, "错误",
          "请指定需要下载的URL");
        return;
    }

    QUrl newUrl = QUrl::fromUserInput(urlSpec);//URL地址
    if (!newUrl.isValid())
    {
        QMessageBox::information(this, "错误",
          QString("无效URL: %1 \n 错误信息: %2").arg(urlSpec, newUrl.errorString()));
        return;
    }

    QString tempDir =ui->editPath->text().trimmed();//临时目录
    if (tempDir.isEmpty())
    {
        QMessageBox::information(this, tr("错误"), "请指定保存下载文件的目录");
        return;
    }

    QString fullFileName =tempDir+newUrl.fileName(); //文件名

    if (QFile::exists(fullFileName))
        QFile::remove(fullFileName);

    downloadedFile =new QFile(fullFileName);//创建临时文件
    if (!downloadedFile->open(QIODevice::WriteOnly))
    {
        QMessageBox::information(this, tr("错误"),"临时文件打开错误");
        return;
    }

    ui->btnDownload->setEnabled(false);

//发送玩过请求,创建网络响应
    reply = networkManager.get(QNetworkRequest(newUrl));
    connect(reply, SIGNAL(finished()), this, SLOT(on_finished()));
    connect(reply, SIGNAL(readyRead()), this, SLOT(on_readyRead()));
    connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
            this, SLOT(on_downloadProgress(qint64,qint64)));
}

void MainWindow::on_editURL_textChanged(const QString &arg1)
{
    Q_UNUSED(arg1);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setValue(0);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/60582.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

生鲜蔬果小程序的完整教程

随着互联网的发展&#xff0c;线上商城成为了人们购物的重要渠道。其中&#xff0c;小程序商城在近年来的发展中&#xff0c;备受关注和青睐。本文将介绍如何使用乔拓云网后台搭建生鲜果蔬配送小程序&#xff0c;并快速上线。 首先&#xff0c;登录乔拓云网后台&#xff0c;进入…

Xilinx A7开发板LVDS IO无输出问题解决方法

使用A7-35T FGG484的FPGA开发板bank16上的IO作为差分LVDS的输入输出&#xff0c;搭建输入输出测试工程发现LVDS可以输入、无法输出。查阅UG471&#xff0c;找到如下信息&#xff1a; 手册中已经针对A7的LVDS做了明确的应用说明&#xff1a; &#xff08;1&#xff09;HP bank上…

客户流失分析预测案例 -- 机器学习项目基础篇(7)

客户流失 它是指现有的客户、用户、订阅者或任何类型的回头客停止与公司开展业务或结束与公司的关系。 客户流失的类型 合同客户流失&#xff1a;当客户签订了服务合同并决定取消服务时&#xff0c;例如有线电视&#xff0c;SaaS。自愿流失&#xff1a;当用户自愿取消服务时…

PHP正则绕过解析

正则绕过 正则表达式PHP正则回溯PHP中的NULL和false回溯案例案例1案例2 正则表达式 在正则中有许多特殊的字符&#xff0c;不能直接使用&#xff0c;需要使用转义符\。如&#xff1a;$,(,),*,,.,?,[,,^,{。 这里大家会有疑问&#xff1a;为啥小括号(),这个就需要两个来转义&a…

XSS漏洞原理及利用跨站请求伪造CSRF

XSS漏洞原理及利用&跨站请求伪造CSRF XSS一、案例二、什么是XSS三、XSS危害四、XSS的分类4.1、反射型XSS4.1.1、介绍4.1.2、利用过程 4.2、存储型XSS4.2.1、介绍4.2.2、利用过程4.2.3、案例 4.3、DOM型XSS4.3.1、介绍4.3.2、常用的DOM方法4.3.3、案例4.3.3.1、代码分析4.3.…

Linux上安装Keepalived,多台Nginx配置Keepalived(保姆级教程)

目录 一、yum安装 第一步&#xff1a;下载 第二步&#xff1a;编辑Keepalived配置文件&#xff08;第一台&#xff09; 第三步&#xff1a;编辑Keepalived配置文件&#xff08;第二台&#xff09; 第四步&#xff1a;我们在本机利用cmd ping一下 一、yum安装 第一步&…

IDEA基础使用

IDEA基础使用 1、IDEA中显示用法和用户截图展示有调用显示无调用显示 对应方法 2、如何找出项目中所有不被调用方法截图展示对应方法 3、常用代码(Code)说明及快捷键:4、未完待续待日后更新。。。总结&#xff1a;欢迎指导&#xff0c;也祝码友们代码越来越棒&#xff0c;技术越…

元素2D转3D 椭圆形旋转实现

椭圆旋转功能展示 transform-style: preserve-3d;&#xff08;主要css代码&#xff09; gif示例&#xff08;背景图可插入透明以此实现边框线的旋转&#xff09; 导致的无法点击遮挡问题可以参考我的另一个文章 穿透属性-----------------------css穿透属性 实时代码展示

【FAQ】在Linux中使用curl访问EasyCVR,返回报错Unauthorized的原因排查

EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&#xff0c;比如&#xff1a;视…

HCIE-Datacom真题和机构资料

通过认证验证的能力 具备坚实的企业网络跨场景融合解决方案理论知识&#xff0c;能够使用华为数通产品及解决方案进行企业园区网络、广域互联网络及广域承载网络的规划、建设、维护及优化&#xff0c;能够胜任企业网络全场景专家岗位&#xff08;包括客户经理、项目经理、售前…

CBCGPRibbon 添加背景图片

resource.h中声明资源的ID&#xff1a;ID_RIBBON_BACKIMAGE rc文件中添加png图片路径&#xff1a; ID_RIBBON_BACKIMAGE PNG DISCARDABLE "res\\bkribbon.png" 代码中添加下测&#xff1a; //添加背景图片 m_wndRibbonBar.SetBackgroundImage(ID_RIB…

使用公式与格式控制Excel快速实现计划甘特图

项目中都会遇到做任务计划的需求&#xff0c;有的客户要求需要有甘特图的形式本文介绍如何使用excel 单元格实现甘特图显示&#xff0c;调整任务时间自动填充单元格填色实现甘特图效果。废话不多说&#xff0c;先看效果。 准备工作先创建两列开始时间与完成时间&#xff0c;这…

EMD经验模态分解介绍

EMD概述 其实一种信号分解方法&#xff0c;是一种自适应的数据处理方法&#xff0c;适合非线性和非平稳时间序列的分析和研究&#xff0c;其本质是对数据序列或信号的平稳化处理。 将上面6个信号叠加如下&#xff1a; 就是6个简单信号叠加&#xff0c;形成一个复杂信号。 核心…

Java精品项目系统第151期大学生校园帮系统打包(编号S063)

Java精品项目系统第151期大学生校园帮系统打包&#xff08;编号S063&#xff09; 大家好&#xff0c;小辰今天给大家介绍一个基于Spring Springboot MyBatis实现的大学生校园帮系统&#xff0c;演示视频文章末尾公众号对号查询观看即可 文章目录 Java精品项目系统第151期大学…

flink1.17 eventWindow不要配置processTrigger

理论上可以eventtime processtime混用,但是下面代码测试发现bug,输入一条数据会一直输出. flink github无法提bug/问题. apache jira账户新建后竟然flink又需要一个账户,放弃 bug复现操作 idea运行代码后 往source kafka发送一条数据 a,1,1690304400000 可以看到无限输出…

etcd

文章目录 etcd单机安装设置键值对watch操作读取键过往版本的值压缩修订版本lease租约&#xff08;过期机制&#xff09;授予租约撤销租约keepAlive续约获取租约信息 事务基于etcd实现分布式锁原生实现官方 concurrency 包实现 服务注册与发现Go 操作 Etcd 参考 etcd etcd 是一…

计算机网络-三种交换方式

计算机网络-三种交换方式 电路交换(Circuit Switching) 电话交换机接通电话线的方式称为电路交换从通信资源分配的角度来看&#xff0c;交换(Switching)就是按照某种方式动态的分配传输线路的资源 电话交换机 为了解决电话之间通信两两之间连线过多&#xff0c;所以产生了电话…

原型模式(Prototype)

原型模式是一种创建型设计模式&#xff0c;使调用方能够复制已有对象&#xff0c;而又无需使代码依赖它们所属的类。当有一个类的实例&#xff08;原型&#xff09;&#xff0c;并且想通过复制原型来创建新对象时&#xff0c;通常会使用原型模式。 The Prototype pattern is g…

解决Pycharm下opencv代码提示问题

解决Pycharm下opencv代码提示问题 新安装了opencv-python4.7.0.72版本&#xff0c;在pycharm中导入cv2后没有代码提示&#xff0c;解决方法如下&#xff1a; 解决方案 我使用的是miniconda环境&#xff0c;opencv安装的路径为&#xff1a;C:\Env\miniconda3\envs\compute\Li…

Vue3和TypeScript项目-移动端兼容

1 全局安装typescript 2 检测安装成功 3 写的是ts代码&#xff0c;但是最后一定要变成js代码&#xff0c;才能在浏览器使用 这样就会多一个js文件 3 ts语法 数组语法 对象语法 安装vue3项目 成功后进入app。安装依赖。因为我们用的是脚手架&#xff0c;要引入东西的时候不需要…