HTTP 客户端

演示了简单的 HTTP 客户端。

本示例演示了简单 HTTP 客户端如何从远程主机获取文件。

本示例的主要工作由 HttpWindow 类完成。因此,我们将重点关注它。

reply.reset(qnam.get(QNetworkRequest(url)));

使用 QNetworkAccessManager,我们开始下载由 url 指定的资源。如果您不熟悉它或使用的函数,或希望更详细地了解它,请查看其文档以及 QNetworkReplyQNetworkRequest 的文档。

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());
    }
}

在本示例中,我们显示了一个对话框,用户可以在其中输入用户名和密码,或取消。取消将导致请求失败。

示例项目 @ code.qt.io

© 2024 Qt公司。本文档中包含的文档贡献均为各自所有者的版权。本提供的文档根据自由软件基金会发布的GNU自由文档许可第1.3版之条款许可。