# 主项目入口

main函数创建对象空间,确认窗口的大小和坐标。

#include #include #include // #include #include "httpwindow.h"int main(int argc, char *argv[]){QApplication app(argc, argv);HttpWindow httpWin;// QDialog的子类const QRect availableSize = httpWin.screen()->availableGeometry();qDebug()<<"availableSize = "<

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目视频教程+代码,C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

# 项目子头文件httpwindow.h

需要的头文件:

QT_BEGIN_NAMESPACEclass QFile;// 文件class QLabel; // 标签class QLineEdit;// 行编辑class QPushButton;// 按钮class QSslError;//QSslError类提供SSL错误class QAuthenticator; // QAuthenticator类提供了一个身份验证对象。class QNetworkReply;// 网络应答class QCheckBox;// 检查盒子QT_END_NAMESPACE

根据给出的类名,以下是各个类的作用的简要介绍:

1. QFile(文件):QFile类提供了对文件的读写操作。它可以用于打开、关闭、读取和写入文件,并提供了一些用于文件操作的便捷方法。

2. QLabel(标签):QLabel类用于显示文本或图像。它通常用于在用户界面中显示静态文本或图像,并且不允许用户进行编辑操作。

3. QLineEdit(行编辑):QLineEdit类提供了一个单行文本编辑框,用于接收用户输入的文本。它可以用于接收单行的用户输入,比如用户名、密码等。

4. QPushButton(按钮):QPushButton类是一个按钮部件,用于触发某些操作或执行特定的功能。当用户单击按钮时,可以连接按钮的信号(clicked)到槽函数,从而实现相关的操作。

5. QSslError(SSL错误):QSslError类提供了有关SSL连接中发生的错误的信息。它用于处理与SSL(Secure Sockets Layer 安全套接字层)相关的错误,如证书验证失败、主机名不匹配等。

6. QAuthenticator(身份验证对象):QAuthenticator类提供了一个身份验证对象,用于在进行网络请求时进行身份验证。它可以用于管理用户名和密码等身份验证信息,并与网络请求一起使用。

7. QNetworkReply:QNetworkReply类用于表示网络请求的响应。它提供了访问响应数据、处理错误和其他网络相关操作的方法。

8. QCheckBox:QCheckBox类是一个复选框部件,用于允许用户选择多个选项。它可以用于表示二进制状态,比如打开/关闭、选中/未选中等。

class ProgressDialog : public QProgressDialog {Q_OBJECTpublic:explicit ProgressDialog(const QUrl &url, QWidget *parent = nullptr);~ProgressDialog();public slots: void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);};

代码解释:

ProgressDialog类的作用是显示一个进度对话框,用于显示网络请求的进度。它通常用于在进行网络请求时显示一个进度条,以便用户可以看到请求的进展情况。

构造函数ProgressDialog(const QUrl &url, QWidget *parent = nullptr)接受一个QUrl类型的参数和一个可选的父部件参数。它用于创建一个ProgressDialog对象,并指定要进行网络请求的URL。

析构函数~ProgressDialog()用于在ProgressDialog对象被销毁时进行清理工作。

networkReplyProgress(qint64 bytesRead, qint64 totalBytes)是一个公共槽函数(public slot),用于处理网络请求的进度更新。它接受两个参数:bytesRead表示已读取的字节数,totalBytes表示总字节数。该槽函数可以在网络请求的过程中更新进度对话框的进度条。

通过继承自QProgressDialog类,ProgressDialog类可以使用QProgressDialog类提供的功能,如设置进度条的范围、设置进度文本等。

class HttpWindow : public QDialog{Q_OBJECTpublic:explicit HttpWindow(QWidget *parent = nullptr);~HttpWindow();void startRequest(const QUrl &requestedUrl);private slots:void downloadFile();void cancelDownload();void httpFinished();void httpReadyRead();void enableDownloadButton();void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);#ifndef QT_NO_SSLvoid sslErrors(QNetworkReply *, const QList &errors);#endifprivate:std::unique_ptr openFileForWrite(const QString &fileName);QLabel *statusLabel;QLineEdit *urlLineEdit;QPushButton *downloadButton;QCheckBox *launchCheckBox;QLineEdit *defaultFileLineEdit;QLineEdit *downloadDirectoryLineEdit;QUrl url;QNetworkAccessManager qnam;QNetworkReply *reply;std::unique_ptr file;bool httpRequestAborted; // http请求已中止};

代码解释:

HttpWindow类的作用是提供一个界面,用于进行HTTP请求和文件下载操作。它包含了一些用于处理HTTP请求和文件下载的槽函数,并使用了Qt的网络模块(QNetworkAccessManager和QNetworkReply)进行网络通信。

构造函数`HttpWindow(QWidget *parent = nullptr)`接受一个可选的父部件参数,并用于创建一个HttpWindow对象。析构函数`~HttpWindow()`用于在HttpWindow对象被销毁时进行清理工作。

`startRequest(const QUrl &requestedUrl)`函数用于开始进行HTTP请求。它接受一个QUrl类型的参数,表示要请求的URL。该函数会初始化网络请求,并发送HTTP请求到指定的URL。

槽函数`downloadFile()`、`cancelDownload()`、`httpFinished()`、`httpReadyRead()`、`enableDownloadButton()`、`slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator)`和`sslErrors(QNetworkReply *, const QList &errors)`分别用于处理下载文件、取消下载、HTTP请求完成、HTTP请求可读、启用下载按钮、处理身份验证和处理SSL错误等操作。

`openFileForWrite(const QString &fileName)`函数是一个私有函数,用于打开一个文件以供写入。它接受一个文件名参数,并返回一个指向QFile的唯一指针,用于写入文件。

HttpWindow类还包含了一些成员变量,如statusLabel(标签部件,用于显示状态信息)、urlLineEdit(行编辑部件,用于输入URL)、downloadButton(按钮部件,用于触发文件下载)、launchCheckBox(复选框部件,用于选择是否启动下载后的文件)、defaultFileLineEdit(行编辑部件,用于指定默认的下载文件名)和downloadDirectoryLineEdit(行编辑部件,用于指定下载文件的目录)等。


## httpwindow.h

#ifndef HTTPWINDOW_H#define HTTPWINDOW_H#include #include #include #include QT_BEGIN_NAMESPACEclass QFile;// 文件class QLabel; // 标签class QLineEdit;// 行编辑class QPushButton;// 按钮class QSslError;//QSslError类提供SSL错误class QAuthenticator; // QAuthenticator类提供了一个身份验证对象。class QNetworkReply;class QCheckBox;QT_END_NAMESPACEclass ProgressDialog : public QProgressDialog {Q_OBJECTpublic:explicit ProgressDialog(const QUrl &url, QWidget *parent = nullptr);~ProgressDialog();public slots: void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);};class HttpWindow : public QDialog{Q_OBJECTpublic:explicit HttpWindow(QWidget *parent = nullptr);~HttpWindow();void startRequest(const QUrl &requestedUrl);private slots:void downloadFile();void cancelDownload();void httpFinished();void httpReadyRead();void enableDownloadButton();void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);#ifndef QT_NO_SSLvoid sslErrors(QNetworkReply *, const QList &errors);#endifprivate:std::unique_ptr openFileForWrite(const QString &fileName);QLabel *statusLabel;QLineEdit *urlLineEdit;QPushButton *downloadButton;QCheckBox *launchCheckBox;QLineEdit *defaultFileLineEdit;QLineEdit *downloadDirectoryLineEdit;QUrl url;QNetworkAccessManager qnam;QNetworkReply *reply;std::unique_ptr file;bool httpRequestAborted;};#endif

## 源文件httpwindow.cpp

#include "httpwindow.h"#include "ui_authenticationdialog.h"#include #include #include #if QT_CONFIG(ssl)// #if QT_CONFIG(ssl) 的目的是检查 Qt 库是否已配置 SSL 模块const char defaultUrl[] = "https://www.baidu.com/";#elseconst char defaultUrl[] = "https://www.baidu.com/";#endifconst char defaultFileName[] = "index.html";// 默认文件名ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent): QProgressDialog(parent){this->setWindowTitle(tr("Download Progress"));this->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); // 移除 WindowContextHelpButtonHint。WindowContextHelpButtonHint 是一个标志,用于表示窗口是否应显示帮助按钮this->setLabelText(tr("Downloading %1.").arg(url.toDisplayString())); // 显示正在下载的文件的名称this->setMinimum(0);this->setValue(0);this->setMinimumDuration(0);this->setMinimumSize(QSize(400, 75)); // 最小窗口}ProgressDialog::~ProgressDialog(){}void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes){setMaximum(totalBytes);setValue(bytesRead);}HttpWindow::HttpWindow(QWidget *parent): QDialog(parent), statusLabel(new QLabel(tr("Please enter the URL of a file you want to download.\n\n"), this)), urlLineEdit(new QLineEdit(defaultUrl)), downloadButton(new QPushButton(tr("Download"))), launchCheckBox(new QCheckBox("Launch file")), defaultFileLineEdit(new QLineEdit(defaultFileName)), downloadDirectoryLineEdit(new QLineEdit), reply(nullptr), file(nullptr), httpRequestAborted(false){setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);setWindowTitle(tr("HTTP"));connect(&qnam, &QNetworkAccessManager::authenticationRequired,this, &HttpWindow::slotAuthenticationRequired);#ifndef QT_NO_SSLconnect(&qnam, &QNetworkAccessManager::sslErrors,this, &HttpWindow::sslErrors);#endifQFormLayout *formLayout = new QFormLayout;urlLineEdit->setClearButtonEnabled(true);connect(urlLineEdit, &QLineEdit::textChanged,this, &HttpWindow::enableDownloadButton);formLayout->addRow(tr("&URL:"), urlLineEdit);QString downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::TempLocation);if (downloadDirectory.isEmpty() || !QFileInfo(downloadDirectory).isDir())downloadDirectory = QDir::currentPath();downloadDirectoryLineEdit->setText(QDir::toNativeSeparators(downloadDirectory));formLayout->addRow(tr("&Download directory:"), downloadDirectoryLineEdit);formLayout->addRow(tr("Default &file:"), defaultFileLineEdit);launchCheckBox->setChecked(true);formLayout->addRow(launchCheckBox);QVBoxLayout *mainLayout = new QVBoxLayout(this);mainLayout->addLayout(formLayout);mainLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));statusLabel->setWordWrap(true);mainLayout->addWidget(statusLabel);downloadButton->setDefault(true);connect(downloadButton, &QAbstractButton::clicked, this, &HttpWindow::downloadFile);QPushButton *quitButton = new QPushButton(tr("Quit"));quitButton->setAutoDefault(false);connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close);QDialogButtonBox *buttonBox = new QDialogButtonBox;buttonBox->addButton(downloadButton, QDialogButtonBox::ActionRole);buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);mainLayout->addWidget(buttonBox);urlLineEdit->setFocus();}HttpWindow::~HttpWindow(){}void HttpWindow::startRequest(const QUrl &requestedUrl){url = requestedUrl;httpRequestAborted = false;reply = qnam.get(QNetworkRequest(url));connect(reply, &QNetworkReply::finished, this, &HttpWindow::httpFinished);connect(reply, &QIODevice::readyRead, this, &HttpWindow::httpReadyRead);ProgressDialog *progressDialog = new ProgressDialog(url, this);progressDialog->setAttribute(Qt::WA_DeleteOnClose);connect(progressDialog, &QProgressDialog::canceled, this, &HttpWindow::cancelDownload);connect(reply, &QNetworkReply::downloadProgress, progressDialog, &ProgressDialog::networkReplyProgress);connect(reply, &QNetworkReply::finished, progressDialog, &ProgressDialog::hide);progressDialog->show();statusLabel->setText(tr("Downloading %1...").arg(url.toString()));}void HttpWindow::downloadFile(){const QString urlSpec = urlLineEdit->text().trimmed();if (urlSpec.isEmpty())return;const QUrl newUrl = QUrl::fromUserInput(urlSpec);if (!newUrl.isValid()) {QMessageBox::information(this, tr("Error"), tr("Invalid URL: %1: %2").arg(urlSpec, newUrl.errorString()));return;}QString fileName = newUrl.fileName();if (fileName.isEmpty())fileName = defaultFileLineEdit->text().trimmed();if (fileName.isEmpty())fileName = defaultFileName;QString downloadDirectory = QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed());bool useDirectory = !downloadDirectory.isEmpty() && QFileInfo(downloadDirectory).isDir();if (useDirectory)fileName.prepend(downloadDirectory + '/');if (QFile::exists(fileName)) {if (QMessageBox::question(this, tr("Overwrite Existing File"),tr("There already exists a file called %1%2." " Overwrite" />setEnabled(false);// schedule the requeststartRequest(newUrl);}std::unique_ptr HttpWindow::openFileForWrite(const QString &fileName){std::unique_ptr file(new QFile(fileName));if (!file->open(QIODevice::WriteOnly)) {QMessageBox::information(this, tr("Error"), tr("Unable to save the file %1: %2.") .arg(QDir::toNativeSeparators(fileName),file->errorString()));return nullptr;}return file;}void HttpWindow::cancelDownload(){statusLabel->setText(tr("Download canceled."));httpRequestAborted = true;reply->abort();downloadButton->setEnabled(true);}void HttpWindow::httpFinished(){QFileInfo fi;if (file) {fi.setFile(file->fileName());file->close();file.reset();}if (httpRequestAborted) {reply->deleteLater();reply = nullptr;return;}if (reply->error()) {QFile::remove(fi.absoluteFilePath());statusLabel->setText(tr("Download failed:\n%1.").arg(reply->errorString()));downloadButton->setEnabled(true);reply->deleteLater();reply = nullptr;return;}const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);reply->deleteLater();reply = nullptr;if (!redirectionTarget.isNull()) {const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());if (QMessageBox::question(this, tr("Redirect"),tr("Redirect to %1 ?").arg(redirectedUrl.toString()),QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {QFile::remove(fi.absoluteFilePath());downloadButton->setEnabled(true);statusLabel->setText(tr("Download failed:\nRedirect rejected."));return;}file = openFileForWrite(fi.absoluteFilePath());if (!file) {downloadButton->setEnabled(true);return;}startRequest(redirectedUrl);return;}statusLabel->setText(tr("Downloaded %1 bytes to %2\nin\n%3") .arg(fi.size()).arg(fi.fileName(), QDir::toNativeSeparators(fi.absolutePath())));if (launchCheckBox->isChecked())QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath()));downloadButton->setEnabled(true);}void HttpWindow::httpReadyRead(){//每当QNetworkReply有新数据时,就会调用此插槽。//我们读取它的所有新数据并将其写入文件。//这样,我们使用的RAM比在finished()时读取时要少//QNetworkReply的信号if (file)file->write(reply->readAll());}void HttpWindow::enableDownloadButton(){downloadButton->setEnabled(!urlLineEdit->text().isEmpty());}void HttpWindow::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator){QDialog authenticationDialog;Ui::Dialog ui;ui.setupUi(&authenticationDialog);authenticationDialog.adjustSize();ui.siteDescription->setText(tr("%1 at %2").arg(authenticator->realm(), url.host()));//URL是否包含信息?填充UI//只有当URL提供的凭据错误时,这才相关ui.userEdit->setText(url.userName());ui.passwordEdit->setText(url.password());if (authenticationDialog.exec() == QDialog::Accepted) {authenticator->setUser(ui.userEdit->text());authenticator->setPassword(ui.passwordEdit->text());}}#ifndef QT_NO_SSLvoid HttpWindow::sslErrors(QNetworkReply *, const QList &errors){QString errorString;for (const QSslError &error : errors) {if (!errorString.isEmpty())errorString += '\n';errorString += error.errorString();}if (QMessageBox::warning(this, tr("SSL Errors"), tr("One or more SSL errors has occurred:\n%1").arg(errorString), QMessageBox::Ignore | QMessageBox::Abort) == QMessageBox::Ignore) {reply->ignoreSslErrors();}}#endif

## ui文件

效果演示

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目视频教程+代码,C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓