C++ Qt 从 QNetworkRequest 获取 HTTP 标头

Posted

技术标签:

【中文标题】C++ Qt 从 QNetworkRequest 获取 HTTP 标头【英文标题】:C++ Qt get HTTP headers from QNetworkRequest 【发布时间】:2013-04-18 14:43:38 【问题描述】:

我正在开发一个 Qt C++ 应用程序。我需要下载一些文件(可能很大)并向用户显示下载进度。要执行此任务,我使用以下代码:

QNetworkAccessManager* networkManager = new QNetworkAccessManager();

QNetworkRequest request(fileUrl); //fileUrl is a QUrl variable
QVariant responseLength = request.header(QNetworkRequest::ContentLengthHeader);
int fileSize = responseLength.toInt();
ui->progressBar->setMaximum(fileSize);
QNetworkReply reply = networkManager->get(request);
QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
                 this, SLOT(downloadProgressChanged(qint64,qint64)));

其中downloadProgressChanged 是具有此代码的插槽:

void downloadProgressChanged(qint64 downloaded, qint64 total)

    ui->progressBar->setValue(ui->progressBar->value() + 1);
    ui->labelProgress->setText(QString::number((downloaded / 1024)));

(我使用名为 progressBar 的 QProgressBar 来显示进度,使用名为 labelProgress 的 QLabel 来显示下载的千字节)。

我的问题是我无法访问 Content-Length 标头(int fileSize 值为 0),因此无法显示操作进度。我检查了我的网络服务器上的 HTTP 标头 - Content-Length 工作正常。

在this SO question 中我读到我可以使用QNetworkReply::metaDataChanged() 信号,但我如何使用它来显示进度?文档说下载已经开始时可以发出信号,但我需要在下载开始之前获取标题内容 - 以设置我的progressBar。

【问题讨论】:

【参考方案1】:

这不是您从请求中获取标头信息的方式:

QNetworkRequest request(fileUrl); //fileUrl is a QUrl variable
QVariant responseLength = request.header(QNetworkRequest::ContentLengthHeader);
int fileSize = responseLength.toInt();
ui->progressBar->setMaximum(fileSize);

尝试使用 QNetworkAccessManager 发出请求,然后从它返回的回复中获取所需的标头。有一种特殊的方法可以仅从请求中检索标头信息:

QNetworkAccessManager::head(const QNetworkRequest & request)

由于 Qt 的网络 API 是异步的,所以你必须将 QNetworkAccessManager 的 finished(QNetworkReply*) 信号连接到一个 slot,并获取 slot 中的 header 信息。

我会这样做:

void MainWindow::on_download_button_clicked()
    QUrl url("http://someurl");
    QNetworkAccessManager * manager = new QNetworkAccessManager(this);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(getHeaders(QNetworkReply*)));
    manager->head(QNetworkRequest(url));


void MainWindow::getHeaders(QNetworkReply * reply)
    if (reply->operation() == QNetworkAccessManager::HeadOperation)
        int content_length = reply->header(QNetworkRequest::ContentLengthHeader).toInt();
    

【讨论】:

【参考方案2】:

您是否尝试过使用 readyRead 信号?在插槽中,您可以准备 GUI。像这样的东西应该做的工作:

connect(reply, SIGNAL(readyRead()), this, SLOT(updateProgressBar()))

【讨论】:

以上是关于C++ Qt 从 QNetworkRequest 获取 HTTP 标头的主要内容,如果未能解决你的问题,请参考以下文章

在 Qt 中,QWebView 和 QNetworkRequest 不能共享 cookie

Qt5 使用 QUrl / QNetworkRequest 将数据发布到服务器

QNetworkRequest 不工作

Qt网络应用开发初步

QT https post请求(QNetworkRequest要设置SSL证书,而SSL证书认证有三种,实测成功)

QT 5.8 Webview 如何进行请求以及如何拦截它?