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

news2024/11/17 9:27:11

文章目录

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux Ubuntu 更新镜像源、安装sudo、nvtop

1.更换镜像源 vi ~/.pip/pip.conf在打开的文件中输入: pip.conf [global] index-url https://pypi.tuna.tsinghua.edu.cn/simple按下:wq保存并退出。 2.安装nvtop 如果输入指令apt install nvtop报错&#xff1a; E: Unable to locate package nvtop 需要更新一下apt&a…

MacBook Pro 16 M1 Max 升级 macOS Ventura 13.5 兼容测评

今天给大家带来了 MacBook Pro 16 M1 Max 升级 macOS Ventura 13.5 兼容 100 挑战赛 的视频&#xff0c;现在充电头再以文章的形式呈现给大家&#xff0c;让大家更清楚、直白的了解这款笔记本在升级系统后的兼容性如何。 MacBook Pro 16 M1 Max 配置了 140W 的 MagSafe 充电口&…

设备管理系统与物联网的融合:实现智能化设备监控和维护

在数字化时代&#xff0c;设备管理系统和物联网技术的融合为工业企业带来了巨大的变革和创新。本文将探讨设备管理系统与物联网的融合&#xff0c;重点介绍设备健康管理平台在实现智能化设备监控和维护方面的关键作用和优势。 一、设备管理系统与物联网的融合 随着物联网技术的…

37.利用linprog解 有约束条件多元变量函数最小值(matlab程序)

1.简述 linprog函数主要用来求线型规划中的最小值问题&#xff08;最大值的镜像问题&#xff0c;求最大值只需要加个“-”&#xff09; 2. 算法结构及使用方法 针对约束条件为Axb或Ax≤b的问题 2.1 linprog函数 xlinprog(f,A,b) xlinprog(f,A,b,Aeq,beq) xlinprog(f,A,b,Aeq,…

PROFINET转ETHERCAT协议网关三菱plc支持ethercat吗

捷米特JM–ECAT-PN是自主研发的一款 PROFINET 从站功能的通讯网关。该产品主要功能是将 PROFINET 网络和 ETHERCAT 网络连接起来。 捷米特JM-ECAT-PN连接到 PROFINET 总线中做为从站使用&#xff0c;连接到 ETHERCAT 总线中做为从站使用。 3.技术参数 PROFINET 技术参数 网关…

软件测试界扎心的谣言:为什么说功能测试是巨坑?

​ 前言 一般而言&#xff0c;想要持续在行业内发展&#xff0c;会选择继续提升自己的测试技能&#xff0c;而目前自动化测试作为业内最主流的技术&#xff0c;往后发展可以进阶到测试开发&#xff0c;但前提条件还是要掌握到足够好的自动化测试技术才行。包括说编程语言的学习…

918. 环形子数组的最大和;2531. 使字符串总不同字符的数目相等;1238. 循环码排列

918. 环形子数组的最大和 核心思想&#xff1a;其实这题不加环形很好做&#xff0c;就是一个动态规划或者贪心就能够解决。加了环形我们应该怎么考虑呢&#xff0c;无非就是两种&#xff0c;第1种是子数组只包含首尾的一个&#xff0c;我们直接求子数组的最大连续和即可&#…

springboot+vue农产品特产商城销售平台_50kf2 多商家

随着我国经济的高速发展与人们生活水平的日益提高&#xff0c;人们对生活质量的追求也多种多样。尤其在人们生活节奏不断加快的当下&#xff0c;人们更趋向于足不出户解决生活上的问题&#xff0c;南阳特产销售平台展现了其蓬勃生命力和广阔的前景。与此同时&#xff0c;为解决…

【Docker晋升记】No.1--- Docker工具核心组件构成(镜像、容器、仓库)及性能属性

文章目录 前言&#x1f31f;一、Docker工具&#x1f31f;二、Docker 引擎&#x1f30f;2.1.容器管理&#xff1a;&#x1f30f;2.2.镜像管理&#xff1a;&#x1f30f;2.3.资源管理&#xff1a;&#x1f30f;2.4.网络管理&#xff1a;&#x1f30f;2.5.存储管理&#xff1a;&am…

Python tkinter 制作文章搜索软件,精准定位想看文章

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 无聊的时候做了一个搜索文章的软件&#xff0c;有没有更加的方便快捷不知道&#xff0c;好玩就行了 环境使用 Python 3.8 Pycharm 模块使用 import requests import tkinter as tk from tkinter import ttk impo…

Vue3_03_setup函数

1.理解&#xff1a;Vue3.0 中的一个新的配置项&#xff0c;值为一个函数。 2.setup是所有组合式 API 表演的舞台。 3.组件中所用到的&#xff1a;数据、方法等等&#xff0c;均要配置在setup中。 4.setup函数的两种返回值&#xff1a; 若返回一个对象&#xff0c;则对象中的…

DirectX12 3D立方体游戏编程选修作业-龙书

DirectX12 3D立方体游戏编程作业-龙书 作业效果配置描述文件参考书签 作业效果 配置描述文件 参考:龙书dx12 chapter-6 电子版在CSDN下载里直接下载的 配置&#xff1a;将龙书中的visual stdio2015修改为visual stdio2019; visual stdio2019组件选择&#xff1a; desktop dev…

C++类和对象入门(下)

C类和对象入门 1. Static成员1.1 Static成员的概念2.2 Static成员的特性 2.友元2.1 友元函数2.2 友元函数的特性2.3 友元类 3. 内部类3.1 内部类的概念和特性 4. 匿名对象5. 再次理解类和对象 1. Static成员 1.1 Static成员的概念 声明为static的类成员称为类的静态成员&…

libtorch::Tensor与Eigen::Tensor互相转换

1. Eigen::Tensor转libtorch::Tensor Eigen::Tensor<float, 3> a{2,4,3};a.setRandom();a(1,2,1) 11.0;/*核心*/torch::Tensor b torch::from_blob(a.data(), {1, a.dimension(2), a.dimension(1), a.dimension(0)});/*核心*/b b.permute({0, 3, 2, 1});std::cout <…

Qt QThread的moveToThread方法使用

Qt线程简介 从 Qt4.4 版本之后&#xff0c;因为 QThread 的 run 方法创建新线程这样实现与 Qt 设计的理念不符&#xff0c;Qt 主推使用 moveToThread 方法来创建新线程。QThread 应该被看做是操作系统线程的接口或控制点&#xff0c;而不应该包含需要在新线程中运行的代码。需…

C++数据结构之BST(二叉搜索树)的实现

目录 01.BST的介绍02.BST 要实现的对外方法03.摘要04.查找节点4.1四个引用&#xff0c;都有妙用4.2递归版4.3非递归版 05.插入节点5.1利用search的返回值5.2更新高度的注意事项5.3插入算法的完整代码 06.删除节点6.1框架6.2单分支&#xff0c;直接替代6.3双分支&#xff0c;化繁…

实现天气预报走势图

实现效果&#xff1a; 这里我用的天气接口是网上开源的&#xff0c;可以自己找一下。 稍微简单封装了一下axiso以及接口 封装的axios&#xff1a; // import { useUserStore } from /stores/user import axios from axios import router from /router import { ElMessage } f…

P14 电路定理——巧妙-灵性-智慧

1、替代定理 图示表示&#xff1a; 叠加定理和齐性定理只能用于线性电路&#xff0c;但是替代定理无论线不线性都可以用。 常见的&#xff1a;线性电路将某复杂支路等效成电压源或电流源之后&#xff0c;就可以使用叠加原理了。 引入两个相互抵消的电压源&#xff0c;拿其中一…

【数字IC基础】低功耗设计

低功耗技术 功耗构成静态功耗(漏电功耗)动态功耗翻转功耗(Switch Power)短路功耗(Internal Power) 不同类型的标准单元的功耗 低功耗设计方法降低芯片工作电压多阈值工艺方法电源门控&#xff08;Power Gating&#xff09;多电压域(Multi-Voltage Domain)体偏置门控时钟一个简单…

AWS Amplify 部署node版本18报错修复

Amplify env&#xff1a;Amazon Linux:2 Build Error : Specified Node 18 but GLIBC_2.27 or GLIBC_2.28 not found on build 一、原因 报错原因是因为默认情况下&#xff0c;AWS Amplify 使用 Amazon Linux:2 作为其构建镜像&#xff0c;并自带 GLIBC 2.26。不过&#xff0c;…