下载大文件 QNetworkreply::readAll 冻结几秒钟

Download big files with QNetworkreply::readAll freeze for a few seconds

我用了像文档这样的例子http://doc.qt.io/qt-4.8/qnetworkaccessmanager.html

我创建一个 startDownload:

connect(pushButton, SIGNAL(clicked(bool)), this, SLOT(startDownload(bool)));

startDownload(bool) 我把这个:

file = new QFile("C:/foo/bar/bigfile.7z");
file->open(QIODevice::WriteOnly);

QNetworkRequest request;
request.setUrl(QUrl("http://localhost/bigfile.7z"));
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");

QNetworkReply *reply = manager->get(request);

connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
        this, SLOT(slotError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
        this, SLOT(slotSslErrors(QList<QSslError>)));

slotReadyRead 我把这个:

file->write(reply->readAll());

但是下载到最后有一个小卡顿2秒然后returns就正常了,下载完成。仅当我尝试传输的文件很大时才会出现此问题。

这是预期的行为。 QIODevice::readAll() 将阻塞线程直到下载完成。根据磁盘速度和缓存策略,QFile::write() 也可能会阻塞。如果文件足够大,readAll() 方法也可能会消耗相当多的 RAM。

最简单的解决方案是使用 read() 而不是 readAll() 以较小的块下载文件。

话虽如此,要找到从网络读取和写入磁盘的完美缓冲区大小并不容易;这将取决于网络连接响应与磁盘写入速度的关系。

在尝试使用@Mike 代码后,我注意到在 readyRead final 中读取的数据比之前的要高得多,这使得写入文件很慢:

最后两个读数是:

  1. 46080000 字节 - 写入大约需要 1.6 秒。
  2. 227323951 字节 - 写入大约需要 2.7 秒。

It varies according to the network type and speed, allowing the buffer to be great or not.

在 GUI 应用程序中,造成约 4 秒的 "freeze" 感觉。

对于我使用的limite buffer QNetworkReply::setReadBufferSize,看看区别:

读取为 1048576 字节 - 写入需要 2 到 10 毫秒。