172 lines
5.3 KiB
C++
172 lines
5.3 KiB
C++
|
#include "downloadworker.h"
|
|||
|
#include <QIODevice>
|
|||
|
#include <QEventLoop>
|
|||
|
#include <QNetworkAccessManager>
|
|||
|
#include <QNetworkRequest>
|
|||
|
#include <QNetworkReply>
|
|||
|
#include <QDebug>
|
|||
|
|
|||
|
DownloadWorker::DownloadWorker(QObject *parent)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void DownloadWorker::setIdentifier(int identifier)
|
|||
|
{
|
|||
|
this->identifier = identifier;
|
|||
|
}
|
|||
|
|
|||
|
void DownloadWorker::setParamter(const QString &url, QPair<qint64, qint64> range)
|
|||
|
{
|
|||
|
this->url = url;
|
|||
|
this->range = range;
|
|||
|
}
|
|||
|
|
|||
|
void DownloadWorker::doWork()
|
|||
|
{
|
|||
|
QNetworkAccessManager *mgr = new QNetworkAccessManager(this);
|
|||
|
QNetworkRequest request;
|
|||
|
request.setUrl(url);
|
|||
|
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
|||
|
request.setRawHeader("Range", QString("bytes=%1-%2").arg(range.first)
|
|||
|
.arg(range.second).toLocal8Bit());
|
|||
|
// QNetworkReply *reply = mgr->get(request);
|
|||
|
// QNetworkReply *reply = mgr->get(request);
|
|||
|
reply = mgr->get(request);
|
|||
|
qint64 writePos = range.first;
|
|||
|
qDebug() << "开始下载数据:" << QString(" %1~%2 -> writePos Start %3")
|
|||
|
.arg(range.first).arg(range.second).arg(writePos);
|
|||
|
// connect(reply, &QNetworkReply::readyRead, [reply, this](){
|
|||
|
//// qDebug() << "测试是否触发,午安啦啦啦";
|
|||
|
// QByteArray data = reply->readAll();
|
|||
|
// qDebug() << "获取到了数据" << " " << data.size();
|
|||
|
// emit resultReady(identifier, data);
|
|||
|
// });
|
|||
|
// connect(reply, &QNetworkReply::errorOccurred, [reply](QNetworkReply::NetworkError error){
|
|||
|
// if (error != QNetworkReply::NoError) {
|
|||
|
// qDebug() << "出错了:" << reply->errorString();
|
|||
|
// }
|
|||
|
// });
|
|||
|
connect(reply, &QNetworkReply::finished, mgr, &QNetworkAccessManager::deleteLater);
|
|||
|
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
|||
|
connect(reply, &QNetworkReply::readyRead, this, &DownloadWorker::dataReady);
|
|||
|
}
|
|||
|
|
|||
|
void DownloadWorker::dataReady()
|
|||
|
{
|
|||
|
QByteArray data = reply->readAll();
|
|||
|
qDebug() << "获取到了数据" << " " << data.size();
|
|||
|
emit resultReady(identifier, data);
|
|||
|
auto controller = qobject_cast<DownloadController*>(parent());
|
|||
|
QMetaObject::invokeMethod(controller, "handleResults", Qt::DirectConnection,
|
|||
|
Q_ARG(int, identifier), Q_ARG(QByteArray, data));
|
|||
|
// QMetaObject::invokeMethod(controller, "handleResults", Qt::QueuedConnection,
|
|||
|
// Q_ARG(int, identifier), Q_ARG(QByteArray, data));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DownloadController::DownloadController(QObject *parent)
|
|||
|
{
|
|||
|
this->threadNum = 4;
|
|||
|
|
|||
|
// 注册信号槽传递的数据类型
|
|||
|
qRegisterMetaType<QPair<qint64, qint64>>("QPair<qint64, qint64>");
|
|||
|
}
|
|||
|
|
|||
|
DownloadController::~DownloadController()
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void DownloadController::setFilename(QString filename)
|
|||
|
{
|
|||
|
this->filename = filename;
|
|||
|
}
|
|||
|
|
|||
|
void DownloadController::setThreadNum(int threadNum)
|
|||
|
{
|
|||
|
this->threadNum = threadNum;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 开始下载
|
|||
|
*/
|
|||
|
void DownloadController::startDownload(const QString &url, qint64 fileSize)
|
|||
|
{
|
|||
|
// 下载任务等分,计算每个线程的下载数据
|
|||
|
qint64 segmentSize = fileSize / threadNum;
|
|||
|
ranges.resize(threadNum);
|
|||
|
// QVector<qint64> writePosList;
|
|||
|
writePosList.resize(threadNum);
|
|||
|
for (int i = 0; i < threadNum; i++) {
|
|||
|
ranges[i].first = i * segmentSize;
|
|||
|
ranges[i].second = i * segmentSize + segmentSize - 1;
|
|||
|
writePosList[i] = ranges[i].first;
|
|||
|
}
|
|||
|
ranges[threadNum-1].second = fileSize; // 余数部分加入最后一个
|
|||
|
|
|||
|
qDebug() << QString("查看分段下载:%1 %2").arg(ranges.size()).arg(writePosList.size());
|
|||
|
// return;
|
|||
|
// 打开文件
|
|||
|
// QFile file;
|
|||
|
file.setFileName(filename);
|
|||
|
if (file.exists())
|
|||
|
file.remove();
|
|||
|
if (!file.open(QIODevice::WriteOnly)) {
|
|||
|
emit errorOccur(file.errorString());
|
|||
|
return;
|
|||
|
}
|
|||
|
file.resize(fileSize);
|
|||
|
|
|||
|
// 创建下载线程
|
|||
|
// qint64 bytesReceived = 0;
|
|||
|
for(int i = 0; i < ranges.size(); i++) {
|
|||
|
qDebug() << QString("第%1个线程:%2-%3").arg(i).arg(ranges.at(i).first).arg(ranges.at(i).second);
|
|||
|
auto worker = new DownloadWorker(this);
|
|||
|
auto range = ranges.at(i);
|
|||
|
worker->setIdentifier(i);
|
|||
|
worker->setParamter(url, range);
|
|||
|
connect(worker, &DownloadWorker::resultReady, this, &DownloadController::handleResults);
|
|||
|
worker->doWork();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 暂停下载
|
|||
|
*/
|
|||
|
void DownloadController::paruseDownload()
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 停止下载
|
|||
|
*/
|
|||
|
void DownloadController::stopDownload()
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 写入响应数据
|
|||
|
* @param identifier 线程编号
|
|||
|
* @param data 请求数据
|
|||
|
*/
|
|||
|
void DownloadController::handleResults(int identifier, QByteArray data)
|
|||
|
{
|
|||
|
qDebug() << QString("测试哈哈哈: %1 --- %2").arg(writePosList.size()).arg(identifier);
|
|||
|
QMutexLocker lock(&mutex);
|
|||
|
qint64 writePos = writePosList.at(identifier);
|
|||
|
file.seek(writePos);
|
|||
|
file.write(data);
|
|||
|
qDebug() << QString("%1, %2, %3").arg(writePos).arg(bytesReceived).arg(data.size());
|
|||
|
writePos += data.size();
|
|||
|
writePosList.replace(identifier, writePos);
|
|||
|
bytesReceived += data.size();
|
|||
|
qDebug() << "已经下载了数据: " << bytesReceived;
|
|||
|
emit receivedProcess(bytesReceived);
|
|||
|
}
|
|||
|
|
|||
|
|