В моем приложении, выполненном с Qt5, я хотел бы установить систему безопасности при загрузке данных из Интернета. Прежде всего, я хочу проверить, сколько байт я загружаю и прервать, если это так. Я хочу установить максимальный лимит загружаемых байтов и прервать его, если он превышен.
я использую QNetworkReply учебный класс.
Прежде всего я проверил размер() функции, но на тот момент я уже получил все данные (запрос завершен), так что этого недостаточно.
Вторая проверка, я посмотрел в сигнал downloadProgress (qint64 bytesReceived, qint64 bytesTotal). Хотя я мог бы это проверить и прервать, если bytesReceived слишком велик. Но я не уверен в двух мотивах: во-первых, как написано в документации
Обратите внимание, что значения как bytesReceived, так и bytesTotal могут отличаться от size (), общего количества байтов, полученных с помощью read () или readAll (), или значения заголовка (ContentLengthHeader). Причиной этого является то, что могут быть служебные данные протокола или данные могут быть сжаты во время загрузки.
Во-вторых, я не знаю когда Я получу этот сигнал …. может быть, будет слишком поздно …
Наконец я проверил setReadBufferSize (размер qint64). Это кажется хорошим решением, но я не уверен насчет следующих двух строк в документации:
первый,
QNetworkReply попытается остановить чтение из сети, как только этот буфер заполнится (то есть, bytesAvailable () возвращает размер или больше)
Что это значит пытаться? я должен полагаться на это?
во-вторых,
В отличие от QAbstractSocket :: setReadBufferSize (), QNetworkReply не может гарантировать точность в размере буфера чтения. То есть bytesAvailable () может возвращать больше, чем размер.
так что, похоже, я не могу рассчитывать на точный лимит, который нужно установить.
Кто-нибудь может подсказать мне лучший способ его реализации?
Лучшее решение, которое я нашел, это использовать readyRead сигнал (QNetworkReply происходит от 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();
}
}
}
Примечание: начальный for(;;)
цикл и проверка if ( currentDataRead.isEmpty() ) return;
нужны для того, чтобы не оставить несколько байтов в конце, потому что мы внутри onReadyRead
это slot
соединен с readyRead
и из документации:
readyRead () не генерируется рекурсивно; если вы повторно войдете в цикл обработки событий или вызовете waitForReadyRead () внутри слота, подключенного к сигналу readyRead (), сигнал не будет повторно отправлен (хотя waitForReadyRead () все еще может возвращать true).
PS: я все еще открыт для лучших решений, возможно, родных в Qt
Других решений пока нет …