HTTP 客户端
演示了简单的 HTTP 客户端。
本示例演示了简单 HTTP 客户端如何从远程主机获取文件。
本示例的主要工作由 HttpWindow 类完成。因此,我们将重点关注它。
reply.reset(qnam.get(QNetworkRequest(url)));
使用 QNetworkAccessManager,我们开始下载由 url
指定的资源。如果您不熟悉它或使用的函数,或希望更详细地了解它,请查看其文档以及 QNetworkReply 和 QNetworkRequest 的文档。
connect(reply.get(), &QNetworkReply::finished, this, &HttpWindow::httpFinished); connect(reply.get(), &QIODevice::readyRead, this, &HttpWindow::httpReadyRead); #if QT_CONFIG(ssl) connect(reply.get(), &QNetworkReply::sslErrors, this, &HttpWindow::sslErrors); #endif
如上所示,我们将响应的一些信号连接到类的槽中。这些槽将处理传入的数据以及完成下载/处理错误。
connect(reply.get(), &QIODevice::readyRead, this, &HttpWindow::httpReadyRead);
关于处理传入数据,由于我们不知道任何潜在输入的最大下载大小,并且我们不希望耗尽可能运行示例程序的任何计算机的内存,我们将在 QNetworkReply::readyRead() 而不是在 QNetworkReply::finished() 中处理传入数据。
void HttpWindow::httpReadyRead() { // This slot gets called every time the QNetworkReply has new data. // We read all of its new data and write it into the file. // That way we use less RAM than when reading it at the finished() // signal of the QNetworkReply if (file) file->write(reply->readAll()); }
然后我们将数据写入到达时。这不太方便,但应用在高峰期将消耗更少的内存!
connect(reply.get(), &QNetworkReply::sslErrors, this, &HttpWindow::sslErrors);
使用 QNetworkReply::sslErrors() 信号,我们还可以处理连接到安全网站(即 HTTPS)时在 TLS 握手过程中可能发生的错误。
void HttpWindow::sslErrors(const QList<QSslError> &errors) { QString errorString; for (const QSslError &error : errors) { if (!errorString.isEmpty()) errorString += '\n'; errorString += error.errorString(); } if (QMessageBox::warning(this, tr("TLS Errors"), tr("One or more TLS errors has occurred:\n%1").arg(errorString), QMessageBox::Ignore | QMessageBox::Abort) == QMessageBox::Ignore) { reply->ignoreSslErrors(); } }
在本示例中,我们向用户显示一个对话框,让他们选择是否忽略这些错误。
QNetworkReply::NetworkError error = reply->error(); const QString &errorString = reply->errorString(); if (error != QNetworkReply::NoError) { QFile::remove(fi.absoluteFilePath()); // For "request aborted" we handle the label and button in cancelDownload() if (!httpRequestAborted) { statusLabel->setText(tr("Download failed:\n%1.").arg(errorString)); downloadButton->setEnabled(true); } return; }
如果发生错误,则 QNetworkReply 将发出 QNetworkReply::errorOccurred() 信号,然后是 QNetworkReply::finished() 信号。在本示例中,我们只连接到后者。通过在相应的槽中删除我们正在写入的文件和处理错误,并使用我们的状态标签显示错误来处理任何潜在的错误。
connect(&qnam, &QNetworkAccessManager::authenticationRequired, this, &HttpWindow::slotAuthenticationRequired);
如果您连接到使用 HTTP 认证 的网站,假设您事先没有提供应该使用的凭据,则您可以在网站请求时处理缺少凭据。使用 QNetworkAccessManager,我们通过将信号 QNetworkAccessManager::authenticationRequired 连接到槽来完成此操作。我们在构造函数中只连接一次。
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())); // Did the URL have information? Fill the UI. // This is only relevant if the URL-supplied credentials were wrong 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()); } }
在本示例中,我们显示了一个对话框,用户可以在其中输入用户名和密码,或取消。取消将导致请求失败。
© 2024 Qt公司。本文档中包含的文档贡献均为各自所有者的版权。本提供的文档根据自由软件基金会发布的GNU自由文档许可第1.3版之条款许可。