Korvo
Korvo

Reputation: 9714

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

I used example like doc http://doc.qt.io/qt-4.8/qnetworkaccessmanager.html

I create a startDownload:

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

In startDownload(bool) I put this:

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>)));

In slotReadyRead I put this:

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

But when the download arrives at the end there is a small freezing 2 seconds and then returns to normal and the download is complete. This problem only occurs if the file I'm trying to transfer is large.

Upvotes: 0

Views: 1782

Answers (2)

Korvo
Korvo

Reputation: 9714

After tried use @Mike code, I noticed that the data read in readyRead final are much higher than the previous which makes it slow to write in file:

without setReadBufferSize

The last two readings are:

  1. 46080000 bytes - takes ~1.6 seconds to write.
  2. 227323951 bytes - takes ~2.7 seconds to write.

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

In GUI applications cause a sense of "freeze" for ~4 secs.

For limite buffer I used QNetworkReply::setReadBufferSize, see the difference:

with setReadBufferSize

The reading was in 1048576 bytes - takes between 2 and 10 msecs to write.

Upvotes: 1

MrEricSir
MrEricSir

Reputation: 8242

This is the expected behavior. QIODevice::readAll() will block the thread until the download completes. It's possible QFile::write() may block as well depending on disk speed and caching policy. The readAll() method may also consume quite a bit of RAM if the file is large enough.

The simplest solution is to download the file in smaller chunks using read() instead of readAll().

Now that said, there's no easy way to find the perfect buffer size to read from the network and write to the disk; it's going to depend on how the network connection responds vs. the disk write speed.

Upvotes: 2

Related Questions