向 QNetworkReply 添加大小限制

Add size limit to QNetworkReply

在我使用 Qt5 完成的应用程序中,我想在从互联网下载数据时设置一个安全系统。首先,我想检查我正在下载多少字节,如果是的话就中止。我想设置下载字节的最大限制,如果超过就中止。

我正在使用 QNetworkReply class.

首先我检查了size()函数,但是那时我已经收到了所有数据(请求完成),所以这还不够。

第二次检查,我查看了信号 downloadProgress(qint64 bytesReceived, qint64 bytesTotal)。不过,如果 bytesReceived 太大,我可以检查并中止。但我不确定有两个动机:首先,如文档中所写

Note that the values of both bytesReceived and bytesTotal may be different from size(), the total number of bytes obtained through read() or readAll(), or the value of the header(ContentLengthHeader). The reason for that is that there may be protocol overhead or the data may be compressed during the download.

其次,我不知道什么时候我会收到这个信号....也许为时已晚...

最后,我检查了setReadBufferSize(qint64 size)。这似乎是一个很好的解决方案,但我不确定文档中的以下两行: 首先,

QNetworkReply will try to stop reading from the network once this buffer is full (i.e., bytesAvailable() returns size or more)

试试是什么意思?我应该依赖它吗?

秒,

Unlike QAbstractSocket::setReadBufferSize(), QNetworkReply cannot guarantee precision in the read buffer size. That is, bytesAvailable() can return more than size.

所以,看来我不能依赖于要设置的精确限制。

有人可以建议我实现它的最佳方法吗?

我找到的最好的解决方案是使用readyRead signal (QNetworkReply derives from QIODevice),然后在slot:

中自己实现安全检查
void onReadyRead()
{
    for (;;)
    {
        QByteArray currentDataRead = httpReply->read(100); // Just read some bytes
        if ( currentDataRead.isEmpty() )
            return;

        myResponseBody.append(currentDataRead);
        if (myResponseBody.size() > myMaxResponseSize) // check my limit
        {
            qDebug() << "Error: response size bigger than expected - aborting";
            httpReply->abort();
        }
    }
}

注意:需要 inifite for(;;) 循环和检查 if ( currentDataRead.isEmpty() ) return; 以便不在末尾遗漏一些字节,因为我们在 onReadyRead 里面,这是一个 slot 连接到 readyRead 并来自文档:

readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

--------------------

PS:我仍然对更好的解决方案持开放态度,可能是 Qt 中的原生解决方案