HTTP 客户端
演示一个简单的 HTTP 客户端。
本例演示了一个简单的 HTTP 客户端如何从远程主机获取文件。
本例的主要工作在 HttpWindow 类中完成。因此,我们将重点关注该类。
reply.reset(qnam.get(QNetworkRequest(url)));
使用QNetworkAccessManager ,我们开始下载url
指向的资源。如果您不熟悉它或使用的函数QNetworkAccessManager::get() ,或者只是想更详细地了解它,请查看它的文档以及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()); } }
在本例中,我们将显示一个对话框,用户可以在其中输入用户名和密码,或者取消请求。取消会导致请求失败。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.