Qt文件下载工具

在Qt中实现文件下载功能,通常可以通过多种方式来完成,包括使用 QNetworkAccessManager 和 QNetworkReply 类,或者使用更高级别的 QHttpMultiPart 类。以下是两种常见的实现方法:

方法1:使用 QNetworkAccessManager 和 QNetworkReply
创建 QNetworkAccessManager 对象:这个对象负责管理和处理网络请求。

发送 GET 请求:使用 QNetworkAccessManager 的 get 方法来发送一个GET请求到指定的URL。

接收数据:通过重写槽函数 readyRead 来接收数据。

保存文件:将接收到的数据写入到文件中。

处理完成:当下载完成后,重写 finished 槽函数来处理完成的逻辑。
请添加图片描述


#ifndef DOWNLOAD_DIALOG_H
#define DOWNLOAD_DIALOG_H#include <QDir>
#include <QDialog>
#include <ui_Downloader.h>namespace Ui {
class Downloader;
}class QNetworkReply;
class QNetworkAccessManager;/*** \brief Implements an integrated file downloader with a nice UI*/
class Downloader : public QWidget
{Q_OBJECTsignals:void downloadFinished (const QString& url, const QString& filepath);public:explicit Downloader (QWidget* parent = 0);~Downloader();bool useCustomInstallProcedures() const;QString downloadDir() const;void setDownloadDir(const QString& downloadDir);public slots:void setUrlId (const QString& url);void startDownload (const QUrl& url);void setFileName (const QString& file);void setUserAgentString (const QString& agent);void setUseCustomInstallProcedures (const bool custom);private slots:void finished();void openDownload();void installUpdate();void cancelDownload();void saveFile (qint64 received, qint64 total);void calculateSizes (qint64 received, qint64 total);void updateProgress (qint64 received, qint64 total);void calculateTimeRemaining (qint64 received, qint64 total);private:qreal round (const qreal& input);private:QString m_url;uint m_startTime;QDir m_downloadDir;QString m_fileName;Ui::Downloader* m_ui;QNetworkReply* m_reply;QString m_userAgentString;bool m_useCustomProcedures;QNetworkAccessManager* m_manager;
};#endif
#pragma execution_character_set("utf-8")
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QMessageBox>
#include <QNetworkReply>
#include <QDesktopServices>
#include <QNetworkAccessManager>#include <math.h>#include "Downloader.h"static const QString PARTIAL_DOWN (".part");Downloader::Downloader (QWidget* parent) : QWidget (parent)
{m_ui = new Ui::Downloader;m_ui->setupUi (this);/* Initialize private members */m_manager = new QNetworkAccessManager();/* Initialize internal values */m_url = "";m_fileName = "";m_startTime = 0;m_useCustomProcedures = false;/* Set download directory */m_downloadDir = QDir::homePath() + "/Downloads/";/* Configure the appearance and behavior of the buttons */m_ui->openButton->setEnabled (false);m_ui->openButton->setVisible (false);connect (m_ui->stopButton, SIGNAL (clicked()),this,               SLOT (cancelDownload()));connect (m_ui->openButton, SIGNAL (clicked()),this,               SLOT (installUpdate()));/* Resize to fit */
}Downloader::~Downloader()
{delete m_ui;delete m_reply;delete m_manager;
}/*** Returns \c true if the updater shall not intervene when the download has* finished (you can use the \c QSimpleUpdater signals to know when the* download is completed).*/
bool Downloader::useCustomInstallProcedures() const
{return m_useCustomProcedures;
}/*** Changes the URL, which is used to indentify the downloader dialog* with an \c Updater instance** \note the \a url parameter is not the download URL, it is the URL of*       the AppCast file*/
void Downloader::setUrlId (const QString& url)
{m_url = url;
}/*** Begins downloading the file at the given \a url*/
void Downloader::startDownload (const QUrl& url)
{/* Reset UI */m_ui->progressBar->setValue (0);m_ui->stopButton->setText (tr ("Stop"));m_ui->downloadLabel->setText (tr ("Downloading updates"));m_ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("unknown"));/* Configure the network request */QNetworkRequest request (url);if (!m_userAgentString.isEmpty())request.setRawHeader ("User-Agent", m_userAgentString.toUtf8());/* Start download */m_reply = m_manager->get (request);m_startTime = QDateTime::currentDateTime().toTime_t();/* Ensure that downloads directory exists */if (!m_downloadDir.exists())m_downloadDir.mkpath (".");/* Remove old downloads */QFile::remove (m_downloadDir.filePath (m_fileName));QFile::remove (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN));/* Update UI when download progress changes or download finishes */connect (m_reply, SIGNAL (downloadProgress (qint64, qint64)),this,      SLOT (updateProgress   (qint64, qint64)));connect (m_reply, SIGNAL (finished ()),this,      SLOT (finished ()));connect (m_reply, SIGNAL (redirected       (QUrl)),this,      SLOT (startDownload    (QUrl)));}/*** Changes the name of the downloaded file*/
void Downloader::setFileName (const QString& file)
{m_fileName = file;if (m_fileName.isEmpty())m_fileName = "QSU_Update.bin";
}/*** Changes the user-agent string used to communicate with the remote HTTP server*/
void Downloader::setUserAgentString (const QString& agent)
{m_userAgentString = agent;
}void Downloader::finished()
{/* Rename file */QFile::rename (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN),m_downloadDir.filePath (m_fileName));/* Notify application */emit downloadFinished (m_url, m_downloadDir.filePath (m_fileName));/* Install the update */m_reply->close();installUpdate();setVisible (false);
}/*** Opens the downloaded file.* \note If the downloaded file is not found, then the function will alert the*       user about the error.*/
void Downloader::openDownload()
{if (!m_fileName.isEmpty())QDesktopServices::openUrl (QUrl::fromLocalFile (m_downloadDir.filePath (m_fileName)));else {QMessageBox::critical (this,tr ("Error"),tr ("Cannot find downloaded update!"),QMessageBox::Close);}
}/*** Instructs the OS to open the downloaded file.** \note If \c useCustomInstallProcedures() returns \c true, the function will*       not instruct the OS to open the downloaded file. You can use the*       signals fired by the \c QSimpleUpdater to install the update with your*       own implementations/code.*/
void Downloader::installUpdate()
{if (useCustomInstallProcedures())return;/* Update labels */m_ui->stopButton->setText    (tr ("Close"));m_ui->downloadLabel->setText (tr ("Download complete!"));m_ui->timeLabel->setText     (tr ("The installer will open separately")+ "...");/* Ask the user to install the download */QMessageBox box;box.setIcon (QMessageBox::Question);box.setDefaultButton   (QMessageBox::Ok);box.setStandardButtons (QMessageBox::Ok | QMessageBox::Cancel);box.setInformativeText (tr ("Click \"OK\" to begin installing the update"));box.setText ("<h3>" +tr ("In order to install the update, you may need to ""quit the application.")+ "</h3>");/* User wants to install the download */if (box.exec() == QMessageBox::Ok) {if (!useCustomInstallProcedures())openDownload();}/* Wait */else {m_ui->openButton->setEnabled (true);m_ui->openButton->setVisible (true);m_ui->timeLabel->setText (tr ("Click the \"Open\" button to ""apply the update"));}
}/*** Prompts the user if he/she wants to cancel the download and cancels the* download if the user agrees to do that.*/
void Downloader::cancelDownload()
{if (!m_reply->isFinished()) {QMessageBox box;box.setWindowTitle (tr ("Updater"));box.setIcon (QMessageBox::Question);box.setStandardButtons (QMessageBox::Yes | QMessageBox::No);box.setText (tr ("Are you sure you want to cancel the download?"));if (box.exec() == QMessageBox::Yes) {m_reply->abort();}}
}/*** Writes the downloaded data to the disk*/
void Downloader::saveFile (qint64 received, qint64 total)
{Q_UNUSED(received);Q_UNUSED(total);/* Check if we need to redirect */QUrl url = m_reply->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl();if (!url.isEmpty()) {startDownload (url);return;}/* Save downloaded data to disk */QFile file (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN));if (file.open (QIODevice::WriteOnly | QIODevice::Append)) {file.write (m_reply->readAll());file.close();}
}/*** Calculates the appropiate size units (bytes, KB or MB) for the received* data and the total download size. Then, this function proceeds to update the* dialog controls/UI.*/
void Downloader::calculateSizes (qint64 received, qint64 total)
{QString totalSize;QString receivedSize;if (total < 1024)totalSize = tr ("%1 bytes").arg (total);else if (total < 1048576)totalSize = tr ("%1 KB").arg (round (total / 1024));elsetotalSize = tr ("%1 MB").arg (round (total / 1048576));if (received < 1024)receivedSize = tr ("%1 bytes").arg (received);else if (received < 1048576)receivedSize = tr ("%1 KB").arg (received / 1024);elsereceivedSize = tr ("%1 MB").arg (received / 1048576);m_ui->downloadLabel->setText (tr ("Downloading updates")+ " (" + receivedSize + " " + tr ("of")+ " " + totalSize + ")");
}/*** Uses the \a received and \a total parameters to get the download progress* and update the progressbar value on the dialog.*/
void Downloader::updateProgress (qint64 received, qint64 total)
{if (total > 0) {m_ui->progressBar->setMinimum (0);m_ui->progressBar->setMaximum (100);m_ui->progressBar->setValue ((received * 100) / total);calculateSizes (received, total);calculateTimeRemaining (received, total);saveFile (received, total);}else {m_ui->progressBar->setMinimum (0);m_ui->progressBar->setMaximum (0);m_ui->progressBar->setValue (-1);m_ui->downloadLabel->setText (tr ("Downloading Updates") + "...");m_ui->timeLabel->setText (QString ("%1: %2").arg (tr ("Time Remaining")).arg (tr ("Unknown")));}
}/*** Uses two time samples (from the current time and a previous sample) to* calculate how many bytes have been downloaded.** Then, this function proceeds to calculate the appropiate units of time* (hours, minutes or seconds) and constructs a user-friendly string, which* is displayed in the dialog.*/
void Downloader::calculateTimeRemaining (qint64 received, qint64 total)
{uint difference = QDateTime::currentDateTime().toTime_t() - m_startTime;if (difference > 0) {QString timeString;qreal timeRemaining = total / (received / difference);if (timeRemaining > 7200) {timeRemaining /= 3600;int hours = int (timeRemaining + 0.5);if (hours > 1)timeString = tr ("about %1 hours").arg (hours);elsetimeString = tr ("about one hour");}else if (timeRemaining > 60) {timeRemaining /= 60;int minutes = int (timeRemaining + 0.5);if (minutes > 1)timeString = tr ("%1 minutes").arg (minutes);elsetimeString = tr ("1 minute");}else if (timeRemaining <= 60) {int seconds = int (timeRemaining + 0.5);if (seconds > 1)timeString = tr ("%1 seconds").arg (seconds);elsetimeString = tr ("1 second");}m_ui->timeLabel->setText (tr ("Time remaining") + ": " + timeString);}
}/*** Rounds the given \a input to two decimal places*/
qreal Downloader::round (const qreal& input)
{return roundf (input * 100) / 100;
}QString Downloader::downloadDir() const
{return m_downloadDir.absolutePath();
}void Downloader::setDownloadDir(const QString& downloadDir)
{if(m_downloadDir.absolutePath() != downloadDir) {m_downloadDir = downloadDir;}
}/*** If the \a custom parameter is set to \c true, then the \c Downloader will not* attempt to open the downloaded file.** Use the signals fired by the \c QSimpleUpdater to implement your own install* procedures.*/
void Downloader::setUseCustomInstallProcedures (const bool custom)
{m_useCustomProcedures = custom;
}

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

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

相关文章

pxe高效网络批量装机

文章目录 一&#xff0c; PXE远程安装服务&#xff08;一&#xff09;三种系统装机的方式&#xff08;二&#xff09;linux装机1. 加载 Boot Loader2. 加载启动安装菜单3. 加载内核和 initrd4. 加载根文件系统5. 运行 Anaconda 安装向导 &#xff08;三&#xff09;实现过程&am…

语言主要是一种交流工具,而不是思维工具?GPT5何去何从?

引言 在人工智能领域&#xff0c;特别是大语言模型&#xff08;LLM&#xff09;的发展中&#xff0c;语言和思维的关系一直是一个备受关注的话题。近期&#xff0c;麻省理工学院&#xff08;MIT&#xff09;在《Nature》杂志上发表了一篇题为《Language is primarily a tool f…

linux进程——概念理解与PCB

前言&#xff1a;本篇讲解Linux进程概念相关内容。 操作系统被称为计算机世界的哲学&#xff0c; 可以见得操作系统的知识并不好理解。 对于这篇进程概念的讲解&#xff0c; 博主认为&#xff0c; 如果没有一些前置知识的话&#xff0c;里面的有些概念并不好理解。 但是如果学习…

SQL Server 用户应当如何防范 Mallox (.hmallox) 勒索软件袭击

勒索软件领域的特点是随着时间的流逝&#xff0c;参与者群体和恶意软件家族都会大量流失&#xff0c;只有少数参与者表现出相对长寿的寿命。曾经令人担忧的威胁&#xff0c;如 REvil 和 Conti&#xff0c;要么被铲除&#xff0c;要么被解散&#xff0c;而其他威胁——例如 ALPH…

UGUI优化篇(更新中)

UGUI优化篇 1. 基础概念2. 重要的类1. MaskableGraphic类继承了IMaskable类2. 两种遮罩的实现区别RectMask2DMask 3. 渲染部分知识深度测试深度测试的工作原理 渲染队列透明物体在渲染时怎么处理为什么透明效果会造成性能问题 1. 基础概念 所有UI都由网格绘制的如image由两个三…

25届平安产险校招测评IQ新16PF攻略:全面解析与应试策略

尊敬的读者&#xff0c;您好。随着平安产险校招季的到来&#xff0c;许多应届毕业生正积极准备着各项测评。本文旨在提供一份详尽的测评攻略&#xff0c;帮助您更好地理解平安产险的校招测评流程&#xff0c;以及如何有效应对。 25届平安产险平安IQ&#xff08;新&#xff09;测…

AI大模型探索之旅:深潜大语言模型的训练秘境

在人工智能的浩瀚星空中&#xff0c;大语言模型无疑是最耀眼的星辰之一&#xff0c;它们以无与伦比的语言理解与生成能力&#xff0c;引领着智能交互的新纪元。本文将带您踏上一场探索之旅&#xff0c;深入大语言模型的训练秘境&#xff0c;揭开其背后复杂而精妙的全景画卷。 …

给 「大模型初学者」 的 LLaMA 3 核心技术剖析

编者按&#xff1a; 本文旨在带领读者深入了解 LLaMA 3 的核心技术 —— 使用 RMSNorm 进行预归一化、SwiGLU 激活函数、旋转编码&#xff08;RoPE&#xff09;和字节对编码&#xff08;BPE&#xff09;算法。RMSNorm 技术让模型能够识别文本中的重点&#xff0c;SwiGLU 激活函…

现在有哪些微服务解决方案?

Dubbo&#xff1a;是一个轻量级的Java微服务框架&#xff0c;最初由阿里巴巴在2011年开源。它提供了服务注册与发现、负载均衡、容错、分布式调用等。Dubbo更多的被认为是一种高性能的RPC框架&#xff08;远程过程调用&#xff09;&#xff0c;一些服务治理功能依赖第三方组件完…

第一部分:C++入门

目录 前言 1、C关键字(C98) 2、命名空间 2.1、命名空间定义 2.2、命名空间的使用 3、C输入&输出 4、缺省参数 4.1、缺省参数的概念 4.2、缺省参数的分类 5、函数重载 5.1、函数重载的概念 5.2、C支持函数重载的原理 6、引用 6.1、引用的概念 6.2、引用特性 …

深圳晶彩智能JC3636W518C开箱实现电脑副屏功能

深圳晶彩智能发布了JC3636W518C 这是一款中国制造的&#xff0c;铝合金外壳&#xff0c;价格非常震撼的开发板。原创是billbill的up播主萨纳兰的黄昏设计的ESP32太极小派&#xff0c;由深圳晶彩智能批量生产。 该款 LCD 模块采用 ESP32-S3R8 芯片作为主控,该主控是双核 MCU&…

C++入门基础篇(2)

欢迎大家的来到小鸥的博客&#xff0c;今天我们继续C基础的第二篇吧&#xff01; 这也是入门基础篇的最后一篇wo~ 目录 1.引用 引用的概念 引用的特性及使用 const常引用 指针和引用的关系 2.inline内联函数 定义 相关特性及使用​ 3.nullptr >>后记<< …

摩尔投票算法

文章目录 什么是摩尔投票算法算法思想 相关例题摩尔投票法的扩展题目解题思路代码奉上 什么是摩尔投票算法 摩尔投票法&#xff08;Boyer-Moore Majority Vote Algorithm&#xff09;是一种时间复杂度 为O(n),空间复杂度为O(1)的方法&#xff0c;它多数被用来寻找众数&#xf…

Manim的代码练习02:在manim中Dot ,Arrow和NumberPlane对象的使用

Dot&#xff1a;指代点对象或者表示点的符号。Arrow&#xff1a;指代箭头对象&#xff0c;包括直线上的箭头或者向量箭头等。NumberPlane&#xff1a;指代数轴平面对象&#xff0c;在Manim中用来创建包含坐标轴的数学坐标系平面。Text&#xff1a;指代文本对象&#xff0c;用来…

Linux系列--命令详解

目录 一、Linux资源管理方式 二、查询类型命令详解 三、文件管理类型命令详解 四、文件压缩与解压 五、文件编辑 六、系统命令 七、文件内容查看命令 一、Linux资源管理方式 linux操作系统采用一个文档树来组织所有的资源。这棵树的根目录的名字叫做&#xff1a;//…

使用 HttpServlet 接收网页的 post/get 请求

前期工作&#xff1a;部署好 idea 和 一个 web 项目 idea(2021),tomcat(9) ->创建一个空的项目 -> 新建一个空的模块 -> 右键单击模块 选择 Add..Fra.. Sup.. -> 勾选Web App...后点击OK -> 点击 file - Project Struc... -> 选择刚刚的模块 -> 点…

Linux - 基础开发工具(yum、vim、gcc、g++、make/Makefile、git)

目录 Linux软件包管理器 - yum Linux下安装软件的方式 认识yum 查找软件包 安装软件 如何实现本地机器和云服务器之间的文件互传 卸载软件 Linux编辑器 - vim vim的基本概念 vim下各模式的切换 vim命令模式各命令汇总 vim底行模式各命令汇总 vim的简单配置 Linux编译器 - gc…

C 语言指针进阶

1.0 指针的定义 指针是内存中一个最小单元的编号&#xff08;内存单元的编号称之为地址【地址就是指针指针就是地址】&#xff09;指针通常是用来存放内存地址的一个变量。本质上指针就是地址&#xff1a;口语上说的指针起始是指针变量&#xff0c;指针变量就是一个变量&#…

MySQL覆盖索引和索引跳跃扫描

最近在深入学习MySQL&#xff0c;在学习最左匹配原则的时候&#xff0c;遇到了一个有意思的事情。请听我细细道来。 我的MySQL版本为8.0.32 可以通过 show variables like version; 查看使用的版本。 准备工作&#xff1a; 先建表&#xff0c;SQL语句如下&#xff1a; c…

SSM框架学习笔记(仅供参考)

&#xff08;当前笔记简陋&#xff0c;仅供参考&#xff09; 第一节课&#xff1a; &#xff08;1&#xff09;讲述了Spring框架&#xff0c;常用jar包&#xff0c;以及框架中各个文件的作用 &#xff08;2&#xff09;演示了一个入门程序 &#xff08;3&#xff09;解释了…