In one of my previous post, I described how a simple download manage with pause/ resume feature can be implemented. Here is post.
After that post I got few request for further explanation or working code sample. So in this post I will describe implementation in more details and provide full working code sample.
I lost older working code because of my laptop crash, so created another sample application for this post, so code might differ a little bit from my older post, but idea is same.
So here code the code.
Following is download function where download request is placed by client.
Following function put download request to QNetworkAccessManager and setup signal slot connection.
Now the interesting functions comes that enable pause/resume functionality to download manager. Following is pause function. If simply abort current request, disconnect the signal/slot so we don't get any error signal and mess with our error handling code and most importantly it write data to our IODevice here its file which is storing downloaded data.
Now the resume function. So most important thing here is "Range" header. It tell the server that I want to start download from this much bytes and not from beginning, because we already received this much data when we paused the request.
Another important function, if you want to show correct progress. Remember to add mDownloadSizeAtPause (number of bytes already downloded when we pause the request ) to bytesReceived and bytesTotal, function to show correct progress.
here is link to full working sample project. Thank you for visiting my blog. Let me know if you need more details.
After that post I got few request for further explanation or working code sample. So in this post I will describe implementation in more details and provide full working code sample.
I lost older working code because of my laptop crash, so created another sample application for this post, so code might differ a little bit from my older post, but idea is same.
So here code the code.
Following is download function where download request is placed by client.
void DownloadManager::download( QUrl url ) { mDownloadSizeAtPause =0; mCurrentRequest = QNetworkRequest(url); mFile = new QFile("download.part"); mFile->open(QIODevice::ReadWrite); download(mCurrentRequest); }
Following function put download request to QNetworkAccessManager and setup signal slot connection.
void DownloadManager::download( QNetworkRequest& request ) { mCurrentReply = mManager->get(request); connect(mCurrentReply,SIGNAL(finished()),this,SLOT(finished())); connect(mCurrentReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgress(qint64,qint64))); connect(mCurrentReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError))); }
Now the interesting functions comes that enable pause/resume functionality to download manager. Following is pause function. If simply abort current request, disconnect the signal/slot so we don't get any error signal and mess with our error handling code and most importantly it write data to our IODevice here its file which is storing downloaded data.
void DownloadManager::pause() { if( mCurrentReply == 0 ) { return; } disconnect(mCurrentReply,SIGNAL(finished()),this,SLOT(finished())); disconnect(mCurrentReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgress(qint64,qint64))); disconnect(mCurrentReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError))); mCurrentReply->abort(); mFile->write( mCurrentReply->readAll()); mCurrentReply = 0; }
Now the resume function. So most important thing here is "Range" header. It tell the server that I want to start download from this much bytes and not from beginning, because we already received this much data when we paused the request.
void DownloadManager::resume() { mDownloadSizeAtPause = mFile->size(); QByteArray rangeHeaderValue = "bytes=" + QByteArray::number(mDownloadSizeAtPause) + "-"; mCurrentRequest.setRawHeader("Range",rangeHeaderValue); download(mCurrentRequest); }
Another important function, if you want to show correct progress. Remember to add mDownloadSizeAtPause (number of bytes already downloded when we pause the request ) to bytesReceived and bytesTotal, function to show correct progress.
void DownloadManager::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal ) { mFile->write( mCurrentReply->readAll() ); int percentage = ((mDownloadSizeAtPause+bytesReceived) * 100 )/ (mDownloadSizeAtPause+bytesTotal); emit progress(percentage); }
here is link to full working sample project. Thank you for visiting my blog. Let me know if you need more details.