在QT中采用多线程下载文件

这里的线程是指下载的通道(和操作系统中的线程不一样),一个线程就是一个文件的下载通道,多线程也就是同时开起好几个下载通道.当服务器提供下载服务 时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配。不难理解,如果你线程多的话,那下载的越快。现流行的下载软件 都支持多线程。

思路:

1:用阻塞的方式获取目标地址的HTTP头部,得到目标文件的大小。

2:算出每段文件的开始点,结尾点,并分别向目标地址发出请求。

3:每次目标地址有数据返回,都将得到的数据写入文件。

4:等待各段文件下载结果。

运行截图:

源代码:

#include <<QtCore>>
#include <<QtNetwork>>//多线程下载的线程数
const int PointCount = 5;
//目标文件的地址(千千静听的下载地址,我用来做实验的)
const QString strUrl = "http://ttplayer.qianqian.com/otherdown/alladin/ttpsetup_5713.exe";//用于下载文件(或文件的一部分)
class Download : public QObject
{Q_OBJECT
private:QNetworkAccessManager m_Qnam;QNetworkReply *m_Reply;QFile *m_File;const int m_Index;qint64 m_HaveDoneBytes;qint64 m_StartPoint;qint64 m_EndPoint;public:Download(int index, QObject *parent = 0);void StartDownload(const QUrl &amp;url, QFile *file, qint64 startPoint=0, qint64 endPoint=-1);
signals:void DownloadFinished();public slots:void FinishedSlot();void HttpReadyRead();
};//用于管理文件的下载
class DownloadControl : public QObject
{Q_OBJECT
private:int m_DownloadCount;int m_FinishedNum;int m_FileSize;QUrl m_Url;QFile *m_File;
public:DownloadControl(QObject *parent = 0);void StartFileDownload(const QString &amp;url, int count);qint64 GetFileSize(QUrl url);
signals:void FileDownloadFinished();private slots:void SubPartFinished();
};Download::Download(int index, QObject *parent)
: QObject(parent), m_Index(index)
{m_HaveDoneBytes = 0;m_StartPoint = 0;m_EndPoint = 0;m_File = NULL;
}void Download::StartDownload(const QUrl &amp;url, QFile *file,qint64 startPoint/* =0 */,qint64 endPoint/* =-1 */)
{if( NULL == file )return;m_HaveDoneBytes = 0;m_StartPoint = startPoint;m_EndPoint = endPoint;m_File = file;//根据HTTP协议,写入RANGE头部,说明请求文件的范围QNetworkRequest qheader;qheader.setUrl(url);QString range;range.sprintf(";Bytes=%lld-%lld";, m_StartPoint, m_EndPoint);qheader.setRawHeader(";Range";, range.toAscii());//开始下载qDebug() << "Part " << m_Index << "start download";m_Reply = m_Qnam.get(QNetworkRequest(qheader));connect(m_Reply, SIGNAL(finished()),this, SLOT(FinishedSlot()));connect(m_Reply, SIGNAL(readyRead()),this, SLOT(HttpReadyRead()));
}//下载结束
void Download::FinishedSlot()
{m_File->flush();m_Reply->deleteLater();m_Reply = 0;m_File = 0;qDebug() << "Part " << m_Index << " download finished";emit DownloadFinished();
}void Download::HttpReadyRead()
{if ( !m_File )return;//将读到的信息写入文件QByteArray buffer = m_Reply->readAll();m_File->seek( m_StartPoint + m_HaveDoneBytes );m_File->write(buffer);m_HaveDoneBytes += buffer.size();
}//用阻塞的方式获取下载文件的长度
qint64 DownloadControl::GetFileSize(QUrl url)
{QNetworkAccessManager manager;qDebug() << ";Getting the file size...";;QEventLoop loop;//发出请求,获取目标地址的头部信息QNetworkReply *reply = manager.head(QNetworkRequest(url));QObject::connect(reply, SIGNAL(finished()), &amp;loop, SLOT(quit()), Qt::DirectConnection);loop.exec();QVariant var = reply->header(QNetworkRequest::ContentLengthHeader);delete reply;qint64 size = var.toLongLong();qDebug() << ";The file size is: "; << size;return size;
}DownloadControl::DownloadControl(QObject *parent)
: QObject(parent)
{m_DownloadCount = 0;m_FinishedNum = 0;m_FileSize = 0;m_File = new QFile;
}void DownloadControl::StartFileDownload(const QString &amp;url, int count)
{m_DownloadCount = count;m_FinishedNum = 0;m_Url = QUrl(url);m_FileSize = GetFileSize(m_Url);//先获得文件的名字QFileInfo fileInfo(m_Url.path());QString fileName = fileInfo.fileName();if (fileName.isEmpty())fileName = ";index.html";;m_File->setFileName(fileName);//打开文件m_File->open(QIODevice::WriteOnly);Download *tempDownload;//将文件分成PointCount段,用异步的方式下载qDebug() << ";Start download file from "; << strUrl;for(int i=0; i<<m_DownloadCount; i++){//先算出每段的开头和结尾(HTTP协议所需要的信息)int start = m_FileSize * i / m_DownloadCount;int end = m_FileSize * (i+1) / m_DownloadCount;if( i != 0 )start--;//分段下载该文件tempDownload = new Download(i+1, this);connect(tempDownload, SIGNAL(DownloadFinished()), this, SLOT(SubPartFinished()));connect(tempDownload, SIGNAL(DownloadFinished()), tempDownload, SLOT(deleteLater()));tempDownload->StartDownload(m_Url, m_File, start, end);}
}void DownloadControl::SubPartFinished()
{m_FinishedNum++;//如果完成数等于文件段数,则说明文件下载完毕,关闭文件,发生信号if( m_FinishedNum == m_DownloadCount ){m_File->close();emit FileDownloadFinished();qDebug() << "Download finished";;}
}#include "main.moc"int main(int argc, char **argv)
{QCoreApplication app(argc, argv);//用阻塞的方式下载文件,完成后退出DownloadControl *control = new DownloadControl;QEventLoop loop;QObject::connect(control, SIGNAL(FileDownloadFinished()), &amp;loop, SLOT(quit()));control->StartFileDownload(strUrl, PointCount);loop.exec();return 0;
}

在QT中采用多线程下载文件相关推荐

  1. Qt中采用多线程实现Socket编程

    Qt中采用多线程实现Socket编程 Socket通常也称作"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 本文介绍的是Qt中采用多线程 ...

  2. 多线程下载文件实践之旅

    目录 1.使用场景 2.多线程下载原理 3.请求如何分段下载 3.1.需要请求的数据如何分段. 3.2.分段下载的数据如何组装成完整的数据文件. 4.关键代码实现 3.成果展现 4.总结 5.参考文章 ...

  3. java 多线程下载文件并实时计算下载百分比(断点续传)

    多线程下载文件 多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来 ...

  4. Java多线程下载文件

    Java多线程下载文件 优化:合理利用服务器资源,将资源利用最大化,加快下载速度 一般有两种方式: 线程池里面有N个线程,多线程下载单个文件,将网络路径的文件流切割成多快,每个线程下载一小部分,然后写 ...

  5. C# 多线程下载文件功能实现,优化文件下载不全问题

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  6. C++中利用WebService下载文件

    C#写的WebService读取文件到byte[]和读取文件内容到string,代码如下: [WebMethod] public byte[] dowloadFile() {     FileStre ...

  7. python多线程下载文件

    看到一篇多线程下载的文章,这里把自己的理解写一篇多线程下载的文章. 我们访问http://192.168.10.7/a.jpg时是get请求,response的head包含Content-Length ...

  8. 【转】QT中添加的资源文件qrc时的路径问题小结

    @2019-06-13 [小记] QT中添加的资源文件qrc时的路径问题小结 转载于:https://www.cnblogs.com/skullboyer/p/11014943.html

  9. java线程下载文件_Java多线程下载文件实例详解

    本文实例为大家分享了Java多线程下载文件的具体代码,供大家参考,具体内容如下 import java.io.File; import java.io.InputStream; import java ...

最新文章

  1. 活动目录迁移之03奔向08 --10月18日2008系列讲座预告篇
  2. legend3---lavarel中使用qq邮箱发送邮件
  3. linux 下去掉^M
  4. Goroutine池
  5. java 怎么把list流化_Java 中的数据流和函数式编程
  6. lintcode:递归打印数字
  7. DirectShow系统初级指南
  8. 总谐波失真计算公式_新能源汽车技术|车用轮毂电机转矩谐波协同控制策略
  9. android 行布局选择器,『自定义View实战』—— 银行种类选择器
  10. c语言第六章条件型循环结构,C语言课件(第六章 循环结构)
  11. html基础标签 1211
  12. 操作系统知识点大总结
  13. 【003】【深入解析Java中volatile关键字的作用】
  14. php矢量瓦片,【教你一招】张海平:如何将小范围在线地图切片数据转换为GIS矢量数据?...
  15. win7(32位)旗舰版共享HP1010打印机给WINXP专业版
  16. 如何利用软文营销将好品牌故事?
  17. IP地址分为几类?各如何表示?IP地址的主要特点是什么?
  18. diamond源码解析
  19. web课程设计网页规划与设计 :旅游景点网站设计——西安(20页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 HTML静态网页作业
  20. 数据库实体联系模型与关系模型

热门文章

  1. 2020疫情期间软件代码安全领域你不得不了解的重要事件
  2. Python爬取HTTPS网站的图片
  3. 四叶草的python代码_驾校一点通2021科目四_科目四安全文明驾驶_科目四模拟考试2021...
  4. Python进阶篇:百度指数解密【抓包JS逆向数据区分】
  5. 【甄选靶场】Vulnhub百个项目渗透——项目十六:FristiLeaks_1.3(文件上传,py脚本改写,sudo提权,脏牛提权,源码获取)
  6. 时差测量的定位精度GDOP公式
  7. 越狱Season 1-Episode 19: The Key
  8. 通过PropertyDescriptor反射进行字段名值的获取及设置
  9. SCP-juruo-002的档案
  10. Thymeleaf contextPath