ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP
خب فایل cpp ما حاوی کد های زیر خواهد بود که در این فایل ما بدنه توابع خودمون رو کامل کردیم و برای دانلود فایلمون همراه با اطلاعات دقیق ارسال و دریافت لازم داریم ! اشاره کنم که خیلی ساده تر از اینها میشه کد دانلود فایل رو توسط http نوشت ولی نیاز دونستم کمی پروژه پیچیده تر رو انتخاب کنم تا نتیجه حاصل از فایل دانلود شده همراه با پکیج های ارسالی و دریافتی همانند سیستم ارسال و دریافت کننده TeamViewer مشخص بشه که ممکنه خیلی ها به این نیاز داشته باشند.
#include "myhttp.h"
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>
MyHttp::MyHttp(QObject *parent) :
QObject(parent)
, _pManager(NULL)
, _pCurrentReply(NULL)
, _pFile(NULL)
, _nDownloadTotal(0)
, _bAcceptRanges(false)
, _nDownloadSize(0)
, _nDownloadSizeAtPause(0)
{
}
MyHttp::~MyHttp()
{
if (_pCurrentReply != NULL)
{
pause();
}
}
void MyHttp::download(QUrl url)
{
qDebug() << "download: URL=" << url.toString();
_URL = url;
{
QFileInfo fileInfo(url.toString());
_qsFileName = fileInfo.fileName();
}
_nDownloadSize = 0;
_nDownloadSizeAtPause = 0;
_pManager = new QNetworkAccessManager(this);
_CurrentRequest = QNetworkRequest(url);
_pCurrentReply = _pManager->head(_CurrentRequest);
_Timer.setInterval(5000);
_Timer.setSingleShot(true);
connect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
_Timer.start();
connect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finishedHead()));
connect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
}
void MyHttp::pause()
{
qDebug() << "pause() = " << _nDownloadSize;
if (_pCurrentReply == NULL)
{
return;
}
_Timer.stop();
disconnect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
disconnect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finished()));
disconnect(_pCurrentReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
disconnect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
_pCurrentReply->abort();
// _pFile->write( _pCurrentReply->readAll());
_pFile->flush();
_pCurrentReply = 0;
_nDownloadSizeAtPause = _nDownloadSize;
_nDownloadSize = 0;
}
void MyHttp::resume()
{
qDebug() << "resume() = " << _nDownloadSizeAtPause;
download();
}
void MyHttp::download()
{
qDebug() << "download()";
if (_bAcceptRanges)
{
QByteArray rangeHeaderValue = "bytes=" + QByteArray::number(_nDownloadSizeAtPause) + "-";
if (_nDownloadTotal > 0)
{
rangeHeaderValue += QByteArray::number(_nDownloadTotal);
}
_CurrentRequest.setRawHeader("Range", rangeHeaderValue);
}
_pCurrentReply = _pManager->get(_CurrentRequest);
_Timer.setInterval(5000);
_Timer.setSingleShot(true);
connect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
_Timer.start();
connect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finished()));
connect(_pCurrentReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
connect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
}
void MyHttp::finishedHead()
{
_Timer.stop();
_bAcceptRanges = false;
QList<QByteArray> list = _pCurrentReply->rawHeaderList();
foreach(QByteArray header, list)
{
QString qsLine = QString(header) + " = " + _pCurrentReply->rawHeader(header);
addLine(qsLine);
}
if (_pCurrentReply->hasRawHeader("Accept-Ranges"))
{
QString qstrAcceptRanges = _pCurrentReply->rawHeader("Accept-Ranges");
_bAcceptRanges = (qstrAcceptRanges.compare("bytes", Qt::CaseInsensitive) == 0);
qDebug() << "Accept-Ranges = " << qstrAcceptRanges << _bAcceptRanges;
}
_nDownloadTotal = _pCurrentReply->header(QNetworkRequest::ContentLengthHeader).toIn t();
// _CurrentRequest = QNetworkRequest(url);
_CurrentRequest.setRawHeader("Connection", "Keep-Alive");
_CurrentRequest.setAttribute(QNetworkRequest::Http PipeliningAllowedAttribute, true);
_pFile = new QFile(_qsFileName + ".part");
if (!_bAcceptRanges)
{
_pFile->remove();
}
_pFile->open(QIODevice::ReadWrite | QIODevice::Append);
_nDownloadSizeAtPause = _pFile->size();
download();
}
void MyHttp::finished()
{
qDebug() << __FUNCTION__;
_Timer.stop();
_pFile->close();
QFile::remove(_qsFileName);
_pFile->rename(_qsFileName + ".part", _qsFileName);
_pFile = NULL;
_pCurrentReply = 0;
emit downloadComplete();
}
void MyHttp::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
_Timer.stop();
_nDownloadSize = _nDownloadSizeAtPause + bytesReceived;
qDebug() << "Download Progress: Received=" << _nDownloadSize << ": Total=" << _nDownloadSizeAtPause + bytesTotal;
_pFile->write(_pCurrentReply->readAll());
int nPercentage = static_cast<int>((static_cast<float>(_nDownloadSiz eAtPause + bytesReceived) * 100.0) / static_cast<float>(_nDownloadSizeAtPause + bytesTotal));
qDebug() << nPercentage;
emit progress(nPercentage);
_Timer.start(5000);
}
void MyHttp::error(QNetworkReply::NetworkError code)
{
qDebug() << __FUNCTION__ << "(" << code << ")";
}
void MyHttp::timeout()
{
qDebug() << __FUNCTION__;
}
در این کلاس تمامی اتفاقانی مثل ارسال / دریافت اطلاعات و تمامی رخداد های موجود در طی دانلود یک فایل رو ایجاد کردیم که هر کدام وظیفه خاص خودش رو خواهد داشت.