下载大文件 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 中读取的数据比之前的要高得多,这使得写入文件很慢:
最后两个读数是:
- 46080000 字节 - 写入大约需要 1.6 秒。
- 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 毫秒。
我用了像文档这样的例子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 中读取的数据比之前的要高得多,这使得写入文件很慢:
最后两个读数是:
- 46080000 字节 - 写入大约需要 1.6 秒。
- 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 毫秒。