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.rhkb.cn/news/376752.html

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

相关文章

LangChain框架详解

LangChain框架详解 LangChain是一个基于语言模型开发应用程序的强大框架&#xff0c;旨在帮助开发人员简化与大模型交互、数据检索以及将不同功能模块串联起来以完成复杂任务的过程。它提供了一套丰富的工具、组件和接口&#xff0c;使开发人员能够轻松构建上下文感知和具备逻…

SwiftUI 截图(snapshot)视频画面的极简方法

功能需求 在 万物皆可截图:SwiftUI 中任意视图(包括List和ScrollView)截图的通用实现 这篇博文中,我们实现了在 SwiftUI 中截图几乎任何视图的功能,不幸的是它对视频截图却无能为力。不过别着急,我们还有妙招。 在上面的演示图片中,我们在 SwiftUI 中可以随心所欲的截图…

机器人相关工科专业课程体系

机器人相关工科专业课程体系 前言传统工科专业机械工程自动化/控制工程计算机科学与技术 新兴工科专业智能制造人工智能机器人工程 总结Reference: 前言 机器人工程专业是一个多领域交叉的前沿学科&#xff0c;涉及自然科学、工程技术、社会科学、人文科学等相关学科的理论、方…

jmeter-beanshell学习9-放弃beanshell

写这篇时候道心不稳了&#xff0c;前面写了好几篇benashell元件&#xff0c;突然发现应该放弃。想回去改前面的文章&#xff0c;看了看无从下手&#xff0c;反正已经这样了&#xff0c;我淋了雨&#xff0c;那就希望别人也没有伞吧&#xff0c;哈哈哈哈&#xff0c;放在第九篇送…

局域网远程共享桌面如何实现

在局域网内实现远程共享桌面&#xff0c;可以通过以下几种方法&#xff1a; 一、使用Windows自带的远程桌面功能&#xff1a; 首先&#xff0c;在需要被控制的电脑上右键点击“此电脑”&#xff0c;选择“属性”。 进入计算机属性界面后&#xff0c;点击“高级系统设置”&am…

【第27章】MyBatis-Plus之Mybatis X 插件

文章目录 前言一、安装指南二、核心功能1.XML 映射跳转2.代码生成3. 重置模板 三、JPA 风格提示四、常见问题解答1. JPA 提示功能无法使用&#xff1f;2. 生成的表名与预期不符&#xff1f; 五、代码生成模板配置1. 默认模板2. 重置默认模板3. 自定义模板内容3.1 实体类信息3.2…

企业智能制造赋能的环境条件为什么重要?需要准备什么样的环境?

在全球制造业不断演进的今天&#xff0c;智能制造已经成为推动行业创新和转型的关键力量。它不仅代表了技术的革新&#xff0c;更是企业管理模式和运营思路的全面升级。然而&#xff0c;智能制造的落地实施并非一蹴而就&#xff0c;它需要企业在环境条件上做好充分的准备&#…

C/C++ list模拟

模拟准备 避免和库冲突&#xff0c;自己定义一个命名空间 namespace yx {template<class T>struct ListNode{ListNode<T>* _next;ListNode<T>* _prev;T _data;};template<class T>class list{typedef ListNode<T> Node;public:private:Node* _…

Web 性能入门指南-1.5 创建 Web 性能优化文化的最佳实践

最成功的网站都有什么共同点&#xff1f;那就是他们都有很强的网站性能和可用性文化。以下是一些经过验证的有效技巧和最佳实践&#xff0c;可帮助您建立健康、快乐、值得庆祝的性能文化。 创建强大的性能优化文化意味着在你的公司或团队中创建一个如下所示的反馈循环&#xff…

Centos7 被停用!如何利用 Ora2Pg 将 Oracle 迁移至 IvorySQL?

在过去的社区讨论中&#xff0c;想要使用或正在使用IvorySQL的社区用户&#xff0c;经常问到Oracle 如何迁移到 IvorySQL 中&#xff0c;而且近期随着 Centos7 官方已经停止维护&#xff0c;这一变动促使了很多将 Oracle 部署在 Centos7 上的 Oracle 用户&#xff0c;开始准备 …

iPhone 16 Pro系列将标配潜望镜头:已开始生产,支持5倍变焦

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 7月6日消息&#xff0c;据DigiTimes最新报道&#xff0c;苹果将在iPhone 16 Pro中引入iPhone 15 Pro Max同款5倍光学变焦四棱镜潜望镜头。 报道称&#xff0c;目前苹果已经将模组订单交至大立光电和玉…

【Linux】Linux背景历史

Linux背景历史 Linux背景Linux是什么&#xff1f;计算机的发展unix发展史Linux发展史开源Linux官网以及版本更替Linux企业应用现状 Linux环境的安装 Linux背景 Linux是什么&#xff1f; Linux(Linux Is Not UniX)&#xff0c;一般指GNU/Linux&#xff0c;是一种免费使用和自由…

[misc]-流量包-wireshark-icmp

wireshark打开&#xff0c;大部分都是icmp,查看data部分 提取data长度&#xff1a; tshark.exe -r 1.pcapng -T fields -e data.len > length.txt 使用python解析这个文件&#xff0c;剔除异常值&#xff0c;每8个取一个值&#xff0c;得到flag ds [] with open(length.tx…

摩尔投票算法

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

Android liveData 监听异常,fragment可见时才收到回调记录

背景&#xff1a;在app的fragment不可见的情况下使用&#xff0c;发现注册了&#xff0c;但是没有回调导致数据一直未更新&#xff0c;只有在fragment可见的时候才收到回调 // 观察通用信息mLightNaviTopViewModel.getUpdateCommonInfo().observe(this, new Observer<Common…

什么是im即时通讯?WorkPlus im即时通讯私有化部署安全可控

IM即时通讯是Instant Messaging的缩写&#xff0c;指的是一种实时的、即时的电子信息交流方式&#xff0c;也被称为即时通讯。它通过互联网和移动通信网络&#xff0c;使用户能够及时交换文本消息、语音通话、视频通话、文件共享等信息。而WorkPlus im即时通讯私有化部署则提供…

Flat Ads:金融APP海外广告投放素材的优化指南

在当今全球化的数字营销环境中,金融APP的海外营销推广已成为众多金融机构与开发者最为关注的环节之一。面对不同地域、文化及用户习惯的挑战,如何优化广告素材,以吸引目标受众的注意并促成有效转化,成为了广告主们亟待解决的问题。 作为领先的全球化营销推广平台,Flat Ads凭借…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(二)-支持高分辨率视频直播应用

引言 本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。…

c#调用c++ dll库报错System.BadImageFormatException

System.BadImageFormatException:“试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)” 1. dll需要选择release模式进行编译 2.选择相同位数&#xff0c;比如x64平台&#xff0c;c#也需要x64 3.不要设置c#不支持的函数供调用 比如&#xff1a; c可以输出到控制台…

5G-A通感融合赋能低空经济-RedCap芯片在无人机中的应用

1. 引言 随着低空经济的迅速崛起&#xff0c;无人机在物流、巡检、农业等多个领域的应用日益广泛。低空飞行器的高效、安全通信成为制约低空经济发展的关键技术瓶颈。5G-A通感一体化技术通过整合通信与感知功能&#xff0c;为低空网络提供了强大的技术支持。本文探讨了5G-A通感…