完成并发下载的进度统计
This commit is contained in:
parent
2d3d35f951
commit
54fa6ff3b6
@ -43,3 +43,52 @@ http://localhost:8080/
|
||||
* https://sucdn.jerrywang.top/
|
||||
* https://store.deepinos.org.cn/
|
||||
|
||||
|
||||
原来的单线程相关代码
|
||||
```cpp
|
||||
// 在处理下载进度的代码中,会一直检测下载是否取消
|
||||
void Widget::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||
{
|
||||
if(totalBytes <= 0) return;
|
||||
download_list[nowDownload-1].setMax(10000); // 最大值
|
||||
download_list[nowDownload-1].setValue((bytesRead*10000)/totalBytes); // 当前值
|
||||
download_size=bytesRead;
|
||||
if(download_list[nowDownload-1].close){ // 随时检测下载是否被取消
|
||||
download_list[nowDownload-1].closeDownload();
|
||||
httpFinished();
|
||||
}
|
||||
}
|
||||
// 但是这里的 download_list[nowDownload-1].close 是在哪里修改的呢?
|
||||
downloadlist download_list[LIST_MAX];
|
||||
download_list 是一个下载进度组件,维持动画的,还不错。
|
||||
|
||||
// 星火商店记录下载进度的代码
|
||||
void Widget::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||
{
|
||||
if(totalBytes <= 0) return;
|
||||
download_list[nowDownload-1].setMax(10000); // 最大值
|
||||
download_list[nowDownload-1].setValue((bytesRead*10000)/totalBytes); // 当前值
|
||||
download_size=bytesRead;
|
||||
if(download_list[nowDownload-1].close){ // 随时检测下载是否被取消
|
||||
download_list[nowDownload-1].closeDownload();
|
||||
httpFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::httpFinished() // 完成下载
|
||||
{
|
||||
file->flush();
|
||||
file->close();
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
delete file;
|
||||
file = nullptr;
|
||||
isdownload=false;
|
||||
isBusy=false;
|
||||
}
|
||||
```
|
||||
|
||||
然后那个多线程下载组件需要的几个功能点:
|
||||
* 下载进度,以及下载速度记录
|
||||
* 下载取消功能
|
||||
* 读取设置,允许设置单线程下载 这个可以放到后面做,优先实现上面两个
|
@ -5,6 +5,7 @@
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
||||
DownloadWorker::DownloadWorker(QObject *parent)
|
||||
{
|
||||
@ -19,59 +20,55 @@ void DownloadWorker::setIdentifier(int identifier)
|
||||
void DownloadWorker::setParamter(const QString &url, QPair<qint64, qint64> range, QFile *file)
|
||||
{
|
||||
this->url = url;
|
||||
// this->range = range;
|
||||
this->startPos = range.first;
|
||||
this->endPos = range.second;
|
||||
this->file = file;
|
||||
}
|
||||
|
||||
qint64 DownloadWorker::getReceivedPos()
|
||||
{
|
||||
return receivedPos;
|
||||
}
|
||||
|
||||
void DownloadWorker::doWork()
|
||||
{
|
||||
QNetworkAccessManager *mgr = new QNetworkAccessManager(this);
|
||||
mgr = new QNetworkAccessManager(this);
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
request.setRawHeader("Range", QString("bytes=%1-%2").arg(startPos)
|
||||
.arg(endPos).toLocal8Bit());
|
||||
// QNetworkReply *reply = mgr->get(request);
|
||||
// QNetworkReply *reply = mgr->get(request);
|
||||
reply = mgr->get(request);
|
||||
// qDebug() << "开始下载数据:" << QString(" %1~%2 -> writePos Start %3")
|
||||
// .arg(range.first).arg(range.second).arg(writePos);
|
||||
qDebug() << "开始下载数据:" << QString(" %1~%2 -> writePos Start %3")
|
||||
.arg(startPos).arg(endPos).arg(receivedPos);
|
||||
// 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::errorOccurred, [this](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);
|
||||
connect(reply, &QNetworkReply::finished, this, &DownloadWorker::slotFinish);
|
||||
connect(reply, &QNetworkReply::downloadProgress, this, &DownloadWorker::handleProcess);
|
||||
|
||||
}
|
||||
|
||||
void DownloadWorker::doStop()
|
||||
{
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
mgr->deleteLater();
|
||||
mgr = nullptr;
|
||||
}
|
||||
|
||||
void DownloadWorker::dataReady()
|
||||
{
|
||||
qDebug() << QString("测试是否执行: %1 %2").arg(startPos).arg(receivedPos);
|
||||
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,
|
||||
file->seek(startPos + receivedPos);
|
||||
file->write(data);
|
||||
qDebug() << QString("%1, %2, %3").arg(startPos).arg(receivedPos).arg(data.size());
|
||||
receivedPos += data.size();
|
||||
// Q_ARG(int, identifier), Q_ARG(QByteArray, data));
|
||||
qDebug() << QString("测试是否执行: %1 %2").arg(startPos).arg(receivedPos);
|
||||
QByteArray data = reply->readAll();
|
||||
file->seek(startPos + receivedPos);
|
||||
file->write(data);
|
||||
receivedPos += data.size();
|
||||
}
|
||||
|
||||
void DownloadWorker::slotFinish()
|
||||
@ -79,23 +76,20 @@ void DownloadWorker::slotFinish()
|
||||
file->flush();
|
||||
qDebug() << "数据块下载完毕:" << QString(" %1~%2 -> writePos Start %3")
|
||||
.arg(startPos).arg(endPos).arg(receivedPos);
|
||||
emit workFinished();
|
||||
}
|
||||
|
||||
void DownloadWorker::handleProcess(qint64, qint64)
|
||||
{
|
||||
emit this->downloadProcess();
|
||||
}
|
||||
|
||||
|
||||
DownloadController::DownloadController(QObject *parent)
|
||||
{
|
||||
this->threadNum = 4;
|
||||
|
||||
// 注册信号槽传递的数据类型
|
||||
qRegisterMetaType<QPair<qint64, qint64>>("QPair<qint64, qint64>");
|
||||
}
|
||||
|
||||
DownloadController::~DownloadController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DownloadController::setFilename(QString filename)
|
||||
{
|
||||
this->filename = filename;
|
||||
@ -111,79 +105,79 @@ void DownloadController::setThreadNum(int threadNum)
|
||||
*/
|
||||
void DownloadController::startDownload(const QString &url, qint64 fileSize)
|
||||
{
|
||||
finish = 0;
|
||||
|
||||
// 下载任务等分,计算每个线程的下载数据
|
||||
this->fileSize = fileSize;
|
||||
qint64 segmentSize = fileSize / threadNum;
|
||||
ranges.resize(threadNum);
|
||||
// QVector<qint64> writePosList;
|
||||
writePosList.resize(threadNum);
|
||||
QVector<qint64> receivedBytes;
|
||||
receivedBytes.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;
|
||||
receivedBytes[i] = 0;
|
||||
}
|
||||
ranges[threadNum-1].second = fileSize; // 余数部分加入最后一个
|
||||
|
||||
qDebug() << QString("查看分段下载:%1 %2").arg(ranges.size()).arg(writePosList.size());
|
||||
// return;
|
||||
// 打开文件
|
||||
file = new QFile;
|
||||
file->setFileName(filename);
|
||||
if (file->exists())
|
||||
file->remove();
|
||||
if (!file->open(QIODevice::WriteOnly)) {
|
||||
delete file;
|
||||
file = nullptr;
|
||||
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);
|
||||
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, file);
|
||||
// connect(worker, &DownloadWorker::resultReady, this, &DownloadController::handleResults);
|
||||
|
||||
workers.append(worker);
|
||||
connect(worker, &DownloadWorker::downloadProcess, this, &DownloadController::handleProcess);
|
||||
connect(worker, &DownloadWorker::workFinished, this, &DownloadController::chunkDownloadFinish);
|
||||
worker->doWork();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 暂停下载
|
||||
*/
|
||||
void DownloadController::paruseDownload()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停止下载
|
||||
*/
|
||||
void DownloadController::stopDownload()
|
||||
{
|
||||
|
||||
for(int i = 0; i < workers.size(); i++) {
|
||||
workers.at(i)->doStop();
|
||||
}
|
||||
file->flush();
|
||||
file->close();
|
||||
delete file;
|
||||
file = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写入响应数据
|
||||
* @param identifier 线程编号
|
||||
* @param data 请求数据
|
||||
*/
|
||||
void DownloadController::handleResults(int identifier, QByteArray data)
|
||||
|
||||
void DownloadController::handleProcess()
|
||||
{
|
||||
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);
|
||||
qint64 bytesReceived = 0;
|
||||
for(int i = 0; i < workers.size(); i++) {
|
||||
bytesReceived += workers.at(i)->getReceivedPos();
|
||||
}
|
||||
qDebug() << QString("下载进度 %1-%2").arg(bytesReceived).arg(fileSize);
|
||||
emit downloadProcess(bytesReceived, fileSize);
|
||||
}
|
||||
|
||||
void DownloadController::chunkDownloadFinish()
|
||||
{
|
||||
finish++;
|
||||
if (finish == threadNum) {
|
||||
emit downloadFinished();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <QList>
|
||||
#include <QFile>
|
||||
#include <QNetworkReply>
|
||||
#include <QMutex>
|
||||
|
||||
class DownloadWorker : public QObject
|
||||
{
|
||||
@ -14,25 +13,29 @@ public:
|
||||
explicit DownloadWorker(QObject *parent = nullptr);
|
||||
void setIdentifier(int identifier);
|
||||
void setParamter(const QString &url, QPair<qint64, qint64> range, QFile *flle);
|
||||
qint64 getReceivedPos();
|
||||
|
||||
public slots:
|
||||
void doWork();
|
||||
void doStop();
|
||||
void dataReady();
|
||||
void slotFinish();
|
||||
void handleProcess(qint64, qint64);
|
||||
|
||||
signals:
|
||||
void resultReady(int identifier, QByteArray data);
|
||||
void testSignals();
|
||||
|
||||
void workFinished();
|
||||
void downloadProcess();
|
||||
|
||||
private:
|
||||
int identifier;
|
||||
QString url;
|
||||
// QPair<qint64, qint64> range;
|
||||
qint64 startPos;
|
||||
qint64 endPos;
|
||||
qint64 receivedPos = 0;
|
||||
QNetworkReply *reply;
|
||||
QNetworkAccessManager *mgr;
|
||||
QFile *file;
|
||||
};
|
||||
|
||||
@ -41,30 +44,28 @@ class DownloadController : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DownloadController(QObject *parent = nullptr);
|
||||
~DownloadController();
|
||||
void setFilename(QString filename);
|
||||
void setThreadNum(int threadNum);
|
||||
void startDownload(const QString &url, qint64 fileSize);
|
||||
void paruseDownload();
|
||||
void stopDownload();
|
||||
|
||||
public slots:
|
||||
void handleResults(int identifier, QByteArray data);
|
||||
// void handleTest();
|
||||
void handleProcess();
|
||||
void chunkDownloadFinish();
|
||||
|
||||
signals:
|
||||
void operate(const QString &url, const QPair<qint64, qint64> &downloadRange);
|
||||
void errorOccur(const QString& msg);
|
||||
void receivedProcess(qint64 number);
|
||||
void downloadProcess(qint64, qint64);
|
||||
void downloadFinished();
|
||||
|
||||
private:
|
||||
int threadNum;
|
||||
QString filename;
|
||||
qint64 fileSize;
|
||||
QVector<QPair<qint64, qint64>> ranges;
|
||||
QFile *file;
|
||||
qint64 bytesReceived;
|
||||
QVector<qint64> writePosList;
|
||||
QMutex mutex;
|
||||
QList<DownloadWorker*> workers;
|
||||
int finish = 0;
|
||||
};
|
||||
|
||||
#endif // FILEDOWNLOADWORKER_H
|
||||
|
@ -255,11 +255,8 @@ void Widget::multiDownloadWithQtConcurrent(const QString &url, qint64 fileSize,
|
||||
|
||||
void Widget::multiDownloadWithQThread(const QString& url, qint64 fileSize, const QString& filename, int threadCount)
|
||||
{
|
||||
DownloadController download;
|
||||
download.setFilename(filename);
|
||||
download.startDownload(url, fileSize);
|
||||
connect(&download, &DownloadController::receivedProcess, [fileSize, this](int receivedNum){
|
||||
int percent = receivedNum / fileSize;
|
||||
ui->downProgressBar->setValue(percent);
|
||||
});
|
||||
DownloadController *download = new DownloadController(this);
|
||||
download->setFilename(filename);
|
||||
download->startDownload(url, fileSize);
|
||||
connect(download, &DownloadController::downloadProcess, this, &Widget::download_progress_change);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user